重新平衡 Deflate 压缩级别
摘要
Klaus Post 讨论了在 Go 压缩库中重新平衡 deflate 压缩级别的过程,以使速度/压缩的权衡更加线性和直观。
<p><a href="https://lobste.rs/s/edtmqj/re_balancing_deflate_compression_levels">评论</a></p>
查看缓存全文
缓存时间: 2026/08/10 15:00
# 重新平衡 Deflate 压缩级别
来源:https://blog.klauspost.com/rebalancing-deflate-compression-levels/
在花了很多时间优化 Go 的 deflate 压缩之后,我发现我的许多基准测试看起来都是这样的:
参考基准测试 (https://usercontent.one/wp/blog.klauspost.com/wp-content/uploads/2016/01/image-3.png) 对 “enwik9” 测试文件进行 gzip 压缩的基准测试。此图表是单个基准测试的可视化结果。纵轴表示速度(MB/s),横轴表示体积缩减。请注意,速度只显示了一个很小的范围,因此大幅度横向跳动并不代表超过几个百分点的差异。
这张图显示了两个主要问题。首先,级别 1 和 2 之间存在很大的跳跃。这并不意外,因为级别 1 使用了一种高度专注于速度的不同算法。其次,级别 5 以上的改进非常微不足道。你没有真正理由选择高于 5 的压缩级别,因为收益太小了。实际上,级别 4 似乎是最合理的设置,因为降到级别 5 时速度损失非常显著(24%,而压缩率只提高 0.7%)。级别 6(当前默认)和级别 9(最佳)之间的压缩差异是 0.25%,但吞吐量却下降了 25%。“级别 6” 的速度是级别 4 的 0.52 倍,换来 3% 的压缩率提升,所以实际上你用了两倍的 CPU 换来了 3% 的网络传输量减少。
当然,这些数字在很大程度上取决于内容类型。然而,如果我们看一下典型 Web 内容压缩的图表,情况几乎是一样的:
典型网站内容基准测试(HTML+JS+CSS+JSON)(https://usercontent.one/wp/blog.klauspost.com/wp-content/uploads/2016/01/image-4.png)。同样,在级别 5 以上没有真正的改进,但速度却有相当大的下降。
## 重新平衡的方法
Balancing Act 2.5(作者 Mike Bitzenhofer)Balancing Act 2.5(CC BY-NC-ND 2.0)作者 Mike Bitzenhofer
考虑到这一点,我开始重新平衡 deflate 压缩级别,使这些权衡更清楚地反映压缩级别。我设定了以下目标:
- 级别 1 和 9 应保持在当前的“端点”。
- 所有压缩级别都应在合理的速度成本下,相对于前一级别提供压缩率提升。
- 速度应该更线性,因此从速度角度看,选择“5”应介于 1 和 9 之间。
压缩总是一项收益递减的事情,你用相对较大的计算成本换取较小的压缩率提升。然而,如果我能够实现更接近这些目标的效果,那么选择压缩级别将更直观,权衡也会更有意义。
那么,如何重新平衡一种压缩方案呢?这正是压缩的“艺术”所在。压缩数据时,没有完美的方法。即使是像 deflate 这样相对简单的算法,也有数百万种组合可以尝试。要在 Web 服务器和一般用途中获得合理速度,需要做出一些假设,用最少的资源去寻找能覆盖大多数情况的压缩机会。这包括在找到“足够好”的匹配时停止搜索历史匹配;还包括跳过看起来不可压缩的数据,限制匹配精度,这样我们就不必为压缩单个请求分配数 GB 的内存。
调整压缩级别远不是一门精确的科学。有些压缩测试会因一个小的调整而获益良多,因为那会让它更适合该数据集。因此,我的测试基于几个不同的测试集:‘enwik9’(http://mattmahoney.net/dc/textdata.html),它是维基百科文章的 XML 转储;‘Matt Mahoney 的 10GB 语料库’(http://mattmahoney.net/dc/10gb.html),包含各种文件;最后还有一个自制的‘Web 服务器测试套件’(http://files.klauspost.com/sites.7z),包含 548 个典型的 Web 服务器文件:HTML、CSS、JavaScript 以及大量小型 JSON 文件。
## 结果
为了获得良好且均衡的设置,我试了很多次。困难之处在于,当你的目标确实是某个特定速度时,不要对它过度优化。如果你过度追求这一点,最终会得到一种设置,用不合理的大量速度换取很小的压缩率提升。只有在非常慢的设置(即级别 8 和 9)下,这才说得过去。首先是我们上面看过的第一个基准测试:
‘enwik9’ 重新平衡后 (https://usercontent.one/wp/blog.klauspost.com/wp-content/uploads/2016/01/image-5.png)。应该可以清楚地看到,现在级别的分布要合理得多。仍有一些需要注意的地方:
- 级别 3 相对于级别 4 并没有显示出明显的速度提升,只损失约 1% 的速度,换来 1% 的压缩率提升。
- 级别 6 和 7 之间存在相当大的差距。这里我们切换了算法。级别 6 不使用“惰性匹配(lazy matching)”,但级别 7 使用。对于这个测试集,使用惰性匹配会使压缩率提高约 1.5%,但吞吐量会降低约 30%。我试图让这两者更接近,但我唯一做到的是让级别 6 变得更慢,而压缩率只提高了一点点。
-
相似文章
极其缓慢的 Level 13 Deflate 压缩
文章描述了 libdeflate 新的级别13,这是一种故意减慢的 DEFLATE 压缩级别,在 Silesia 数据集上仅能实现微不足道的压缩提升(0.134%),但代价是比级别12慢56倍,专为数据压缩一次、解压多次的场景设计。
Lean中快速的DEFLATE压缩
一篇博客文章展示,经形式化验证的Lean实现的DEFLATE压缩算法在典型级别上,其速度和压缩比均优于纯Rust实现。作者将此归因于能够安全地让AI代理优化代码,并依赖形式化证明来保证正确性。
Postgres 19 压缩:从 pglz 到 LZ4
PostgreSQL 19 计划将默认的 TOAST 压缩算法从 pglz 改为 LZ4,提供更好的性能和效率。文章介绍了 Postgres 压缩的历史以及切换的原因。
通过穷举搜索实现无损GIF压缩
博客文章探讨了通过对LZW编码进行穷举搜索来实现GIF图像的无损重新压缩,类似于PNG的Zopfli方法,以达到更小的文件大小。
Codec-Gauge:为Transformer KV缓存学习压缩友好的变换框架
Codec-Gauge 为Transformer KV缓存学习小型正交通道变换(度量),以在固定比特率下提高压缩保真度,显著降低多个模型和后端上的KL散度。