高性能压缩算法除存储效率外的用途及压缩IO更快的原因
核心原因:你漏算了IO瓶颈的权重
你之前的推导前提是「所有数据处理步骤的耗时都在同一量级」,但实际计算机系统里,不同存储介质的速度差能达到好几个数量级,这才是加了压缩解压步骤反而可能更快的核心原因:
- 消费级机械硬盘连续读写速度通常在100200MB/s,随机IO速度还要再低12个数量级
- 普通SATA SSD连续读写约500MB/s,主流NVMe SSD连续读写大概3~7GB/s
- 现代单核CPU跑轻量压缩算法的解压速度可以做到数GB到十几GB/s,内存读写速度更是能到几十GB/s
当IO带宽成为整个流程的瓶颈时,花极少的CPU时间把数据压小,减少实际需要读写的IO数据量,总耗时反而会更低。
举个最直观的算账例子:假设你有10GB的原始资源,用LZ4压缩后体积是4GB,存储用的是连续读速度5GB/s的NVMe SSD:
- 直接读原始数据:纯IO耗时
10GB / 5GB/s = 2s,CPU几乎无额外开销,总耗时2s - 读压缩数据:IO读4GB耗时
4GB / 5GB/s = 0.8s,CPU按10GB/s的LZ4解压速度把4GB压缩包还原成10GB原始数据,耗时0.4s,总耗时1.2s,比直接读快40%
你提到的「Huffman编码这类基础压缩算法也要额外遍历数据、做编解码」的问题其实不成立:Huffman解码本质是固定表查表操作,单字节处理的CPU开销极低,这部分操作全在内存里完成,速度比IO高几个量级,省下来的IO成本完全可以覆盖编解码开销。你之前的认知误区在于默认「要读取原始大小的完整数据」,但压缩场景下从IO链路读到的根本不是原始体积的数据,遍历原始数据的步骤是在内存里完成的,和从磁盘/网络读大块数据的成本完全不是一个量级。
这种速度收益不是所有场景都成立:
- 当IO速度足够快、或者数据本身可压缩性极低(比如已经压缩过的视频、加密数据)、或者用的压缩算法编解码速度太慢时,加压缩步骤反而会拖慢速度
- 只有当「压缩后节省的IO耗时 > 压缩/解压的CPU耗时」时,压缩才会带来速度提升,LZ4、Snappy这类轻量压缩算法就是专门卡在这个平衡点设计的,甚至在不少SSD场景下都能拿到正收益。
U++ 重度依赖zlib的设计考量
这个设计不是只为了省存储空间,是多维度权衡后的结果:
- 首先是分发和存储效率的硬需求:U++本身主打静态编译、单文件分发的RAD开发体验,把图标、UI布局、本地化文本、内置脚本等资源用zlib压缩后打包进单EXE,能把最终发布的程序体积压到原来的1/3~1/2,不管是用户下载、安装还是磁盘存储的体验都好很多。
- 确实包含速度优化的考量:
- 资源压缩是构建阶段预执行的:开发者编译程序的时候就已经把所有资源压成zlib格式了,用户端运行程序时根本不需要付出压缩的CPU开销,只需要做解压。对用户来说,冷启动读资源时少读百分之几十的磁盘数据,省下来的IO时间完全可以覆盖zlib解压的开销——尤其是机械盘用户占比不低的场景下,压缩后的资源加载速度反而比读原始资源快。
- 降低运行时内存压力:压缩的资源可以按需读取、按需解压,不需要把所有原始资源一次性加载到内存里铺开,对资源量较大的应用来说,能明显降低峰值内存占用。
- zlib本身的特性刚好匹配资源打包的场景:zlib没有专利限制,所有平台都有成熟稳定的实现,解压速度稳定在数百MB/s,压缩率也比LZ4这类极致速度的算法高不少。毕竟资源是一次性预压缩的,构建时压缩慢几秒用户完全感知不到,只要用户端解压速度够快、压缩率够高,就是非常合适的选择。
如果是U++里运行时频繁读写的临时数据、缓存数据,它一般也不会硬套zlib,会根据场景选择更快的轻量压缩或者直接无压缩读写,不会为了压缩率牺牲运行时速度。
内容的提问来源于stack exchange,提问作者mindoverflow
相关产品推荐
相关产品推荐

