【问题标题】:Difference: LZ77 vs. LZ4 vs. LZ4HC (compression algorithms)?区别:LZ77 vs. LZ4 vs. LZ4HC(压缩算法)?
【发布时间】:2015-02-20 18:09:37
【问题描述】:

我了解 LZ77 和 LZ78 算法。 我阅读了 LZ4 herehere 并找到了 code for it

这些链接描述了 LZ4 块格式。但如果有人可以解释(或引导我到一些资源解释),那就太好了:

  • LZ4 与 LZ77 有何不同?
  • LZ4HC 与 LZ4 有何不同?
  • 是什么想法让 LZ4HC 算法这么快?

【问题讨论】:

  • 您有多个问题都纠结在一起。必须写一个 10 页的回复来涵盖所有这些。
  • @swdev (虽然你说的是真的,但我尝试写了那个古老的回复:))

标签: lossless-compression lz4 lz77


【解决方案1】:

LZ4 旨在快速压缩,每个内核可达到数百 MB/s。它适用于您需要非常便宜的压缩的应用程序:例如,您正在尝试使网络或磁盘格式更紧凑,但不能在压缩上花费大量 CPU 时间。例如,它位于具有snappyLZO 的家庭中。

自然的比较点是 zlib 的DEFLATE algorithm,它使用了LZ77Huffman coding,并用于gzip、.ZIP 和.PNG 格式,以及其他太多的地方。

这些快速压缩器的不同之处在于:

  1. 他们使用更快的重复检测代码(通常是一个简单的hashtable,没有冲突检测),但不会搜索多个可能的匹配项以找到最佳匹配项(这需要时间但会导致更高的压缩率),并且可以'找不到一些短匹配。
  2. 他们只尝试压缩输入中的重复 - 他们不尝试利用某些字节比其他字节更有可能重复之外。
  3. 与 2 密切相关,它们一次生成输出字节,而不是位;允许字节码的小数部分有时会允许更多的压缩,但需要更多的 CPU 工作(通常是位移、掩码和分支)来编码和解码。
  4. 为了在现代 CPU 上快速实现它们,我们进行了大量实际工作。

相比之下,DEFLATE 的压缩效果更好,但压缩和解压缩速度较慢,而像 LZMAbzip2LZHAMbrotli 这样的高压缩算法往往需要更多时间(尽管 Brotli at its faster settings can compete with zlib) .高压缩算法之间有很多变化,但从广义上讲,它们倾向于捕获更长距离的冗余,更多地利用上下文来确定可能的字节,并使用更紧凑但更慢的方式以比特表示它们的结果。

LZ4HC 是 LZ4 的“高压缩”变体,我相信它改变了上面的第 1 点——压缩器在当前和过去的数据之间找到不止一个匹配,并寻找最佳匹配以确保输出很小。与 LZ4 相比,这提高了压缩比率,但降低了压缩速度。不过解压速度不受影响,所以如果你压缩一次并解压多次,并且最想要非常便宜的解压,LZ4HC 是有意义的。

请注意,即使是快速压缩器,也可能不允许一个内核饱和大量带宽,例如 SSD 或快速数据中心内链路提供的带宽。还有更快的压缩比更低,有时用于temporarily pack data in RAMWKdmDensity 是两个这样的压缩机;他们共有的一个特点是一次作用于输入的 4 字节机器字,而不是单个字节。有时专门的硬件可以实现非常快速的压缩,例如Samsung's Exynos chipsIntel's QuickAssist technology

如果你对压缩比 LZ4 更多但 CPU 时间比 deflate 更少的东西感兴趣,LZ4 的作者 (Yann Collet) 写了一个名为 Zstd 的库——这里有一个 blog post from Facebook at its stable release,背景是 finite state machines用于紧凑地编码重复信息,以及detailed description in an RFC。它的fast modes 可以在一些 LZ4-ish 用例中工作。 (此外,Apple 根据类似的原则开发了lzfse,而 Google 开发了 gipfeli 作为“中等”打包程序。两者似乎都没有在外界得到太多使用。)此外,一些项目旨在提供更快/更轻的 DEFLATE: SLZpatches to zlib by CloudFlare and Intel

与最快的压缩器相比,那些“中等”打包器添加了一种熵编码,也就是说,它们利用了某些字节比其他字节更常见的优势,并且(实际上)将对于更常见的字节值,输出中的位数更少。

如果您正在压缩一个长流,并且使用更多内核加快速度可能会有所帮助,则可以通过pigz 和 zstd 通过命令行工具的-T 选项(以及在库中)使用并行压缩)。 (也有 various 实验性的 packers,但它们的存在更多是为了突破速度或密度的界限,而不是今天使用。)

因此,总的来说,您可以为不同的应用提供相当多的替代压缩器:

  • 对于非常快速的压缩:LZ4、zstd 的最低设置,甚至更弱的内存压缩器
  • 对于平衡压缩:DEFLATE 是旧标准;中低设置的 Zstd 和 brotli 是新用途的不错选择
  • 对于高压缩:brotli 或 Zstd(高设置)
  • 对于非常高的压缩率(例如压缩一次并提供多次的静态内容):brotli

当您从 LZ4 移动到 DEFLATE 到 brotli 时,您需要付出更多努力来预测和编码数据,并以牺牲一些速度为代价获得更多的压缩。

顺便说一句,像 brotli 和 zstd 这样的算法通常可以胜过 gzip——在给定的速度下压缩得更好,或者更快地获得相同的压缩——但这实际上并不是因为 zlib 做错了什么错误。主要秘密可能是较新的算法可以使用更多内存:zlib 可以追溯到 1995 年(并且 DEFLATE 可以追溯到 1993)。那时的 RAM cost > 3,000 倍于今天,所以只保留 32KB 的历史记录是有意义的。 CPU 随时间的变化也可能是一个因素:大量的算术(用于有限状态机)比以前便宜,而不可预测的ifs(分支)相对更贵。

【讨论】:

  • 请再看一页,你也忘了描述 LZ77 以及它的不同之处 :-)
  • @twotwotwo 写得很好。我知道这可能超出了范围,但是github.com/pieroxy/lz-string 呢?你觉得这个算法比 LZ4 快吗?
  • @NiCkNewman -- 它受限于必须在 JS 虚拟机中运行,而 LZ4 可以使用优化的 C 或汇编。 JavaScript 引擎在他们所做的事情上令人惊叹,但仍然不像经过调整的本机代码。它可能更慢。不过,它可能仍然是适合您特定工作的工具。
  • 我同意,加入 lz77/gzip 会很棒。它与 lzma 有何不同。
  • @NiCkNewman 我是 LZ-String 的作者。它并不比 LZ4 快,因为它基本上是一个 LZW 实现,带有一些技巧以将其输出适合字符串。这是我选择的一个非常古老的算法,因为在我编写库时它是免费的,并且实现起来非常简单。就速度而言,它可能与 zlib 相当,但在压缩率方面更差。
猜你喜欢
  • 1970-01-01
  • 2014-02-03
  • 2016-06-17
  • 1970-01-01
  • 1970-01-01
  • 2016-10-07
  • 1970-01-01
  • 1970-01-01
  • 2013-06-12
相关资源
最近更新 更多