LZ4 是一种快速压缩算法,每个核心可达到数百 MB/s 的压缩速度。它适用于需要非常便宜的压缩的应用程序:例如,您正在尝试使网络或磁盘格式更紧凑,但不能花费大量 CPU 时间进行压缩。它与 snappy 和 LZO 等算法属于同一类型。
自然的比较点是 zlib 的 DEFLATE 算法,它使用 LZ77 和 Huffman 编码,并被用于 gzip、.ZIP 和 .PNG 格式等太多地方以至于无法计数。
这些快速压缩器之间的区别在于:
- 他们使用重复检测代码,通常是一个没有冲突检测的简单哈希表,速度更快,但不会在多个可能的匹配项中搜索最佳匹配项(这需要时间但可以获得更高的压缩率),并且无法找到一些短匹配项。
- 他们只尝试压缩输入中的重复内容,而不尝试利用某些字节比其他字节更有可能出现的情况 在 重复之外。
- 与第二点密切相关,他们一次生成字节输出,而不是位;允许分数字节码有时可以实现更好的压缩,但需要更多的CPU工作(通常是位移和掩码和分支)来编码和解码。
- 大量的实际工作已经投入到使它们在现代CPU上实现快速。
相比之下,DEFLATE 获得更好的压缩率,但压缩和解压速度较慢,而像
LZMA、
bzip2、
LZHAM 或
brotli 这样的高压缩算法往往需要更多时间(尽管
Brotli 在更快的设置下可以与 zlib 竞争)。高压缩算法之间存在很大差异,但总体上,它们往往捕获更长距离的冗余,更充分地利用上下文来确定哪些字节是可能的,并使用更紧凑但更慢的方式将结果表达为位。
LZ4HC是LZ4的“高压缩”变种,我认为它改变了上述第一点——压缩器在当前数据和过去数据之间找到多个匹配项,并寻找最佳匹配项以确保输出尽可能小。这提高了压缩比,但与LZ4相比降低了压缩速度。但解压速度不会受到影响,因此,如果您只需要进行一次压缩并且多次解压缩,而且大多数情况下需要极其便宜的解压缩,则使用LZ4HC是有意义的。
请注意,即使是快速的压缩器也可能无法使一个核心饱和大量带宽,例如SSD或快速数据中心链接提供的带宽。甚至有更快的压缩器,比如用于临时将数据打包到RAM中的
WKdm和
Density,它们共享的一个特点是一次处理4字节的机器字而不是单独的字节。有时候专门的硬件可以实现非常快的压缩,例如
三星的Exynos芯片或
Intel的QuickAssist技术。
如果您想要比LZ4更加压缩,但CPU时间比deflate少的话,LZ4的作者Yann Collet编写了一个名为
Zstd的库--这里有一个
Facebook在其稳定版本发布时的博客文章,介绍了用于紧凑编码重复信息的
有限状态机的背景知识,以及在RFC中的
详细描述。它的
快速模式可以在某些类似于LZ4的用例中使用。(此外,苹果公司基于类似原则开发了
lzfse,而谷歌公司则开发了
gipfeli作为“中等”压缩器。两者似乎在外部世界中并没有得到很多使用。) 此外,一些项目旨在提供更快/更轻的DEFLATE:
SLZ,
由CloudFlare和Intel提供的zlib补丁。(还进行了
针对大型现代CPU核心的快速解压缩工作。)
与最快的压缩器相比,这些“中等”打包程序添加了一种形式的熵编码,也就是说,它们利用了某些字节比其他字节更常见的特点,并且(实际上)在输出中为更常见的字节值放置较少的位。
如果您正在压缩一个长流,并且使用更多核心可以加快速度,则通过
pigz和zstd通过命令行工具的
-T
选项(以及库中)提供并行压缩。 (还有
各种实验性
打包程序,但它们更多地存在于推动速度或密度的边界,而不是今天的使用。)
因此,总体而言,您对于不同应用程序有一个相当好的备选压缩程序谱系:
- 对于非常快的压缩:LZ4、zstd 的最低设置,甚至更弱的内存压缩器
- 对于平衡的压缩:DEFLATE 是旧标准;Zstd 和 Brotli 在低到中等设置上是新用途的良好替代品
- 对于高度压缩:Brotli,或 Zstd 在高设置上
- 对于非常高的压缩(例如静态内容只压缩一次并多次提供服务):Brotli
当您从 LZ4 到 DEFLATE 再到 Brotli 时,您会增加更多预测和编码数据的努力,并在某些速度上获得更多的压缩。
作为旁注,像Brotli和Zstd这样的算法通常可以优于gzip——在给定速度下更好地压缩,或者更快地获得相同的压缩效果——但这并不是因为zlib做错了什么。主要的秘密可能是新算法可以使用更多的内存:zlib可以追溯到1995年(DEFLATE到1993年)。当时,RAM的成本比今天高出3000倍以上,因此保留32KB的历史记录是有意义的。随着时间的推移,CPU的变化也可能是一个因素:有限状态机中使用的大量算术运算相对便宜,而不可预测的if语句(分支)相对更昂贵。