Java Deflater策略 - DEFAULT_STRATEGY、FILTERED和HUFFMAN_ONLY

8
我正在尝试在压缩Java webapp响应时,在性能和压缩程度之间找到平衡点。通过查看Deflater类,我可以设置级别和策略。级别很明显,从“BEST_SPEED”到“BEST_COMPRESSION”。但是,对于策略,“DEFAULT_STRATEGY”,“FILTERED”和“HUFFMAN_ONLY”我并不确定。我可以从Javadoc中理解一些内容,但我想知道是否有人在他们的应用程序中使用了特定的策略,并且是否在性能/压缩程度方面看到了任何差异。
1个回答

18
Java Deflater中提到的策略选项起源于ZLIB(C)实现的RFC 1950和DEFLATE(1951),我相信它们存在于几乎所有实现DEFLATE的压缩库中。
要理解它们的含义,您需要了解一些关于DEFLATE的知识。压缩算法结合了LZ77和Huffman编码。基本原理如下:
LZ77压缩通过查找重复的数据序列来实现。实现通常使用大小在1k到32k之间的"滑动窗口",以跟踪前面的数据。对于原始数据中的任何重复项,LZ77压缩将插入一个"回溯引用",而不是将重复的数据插入输出。想象一下回溯引用说"在此处插入您在8293个字节之前看到的相同数据,共17个字节"。回溯引用被编码为这对数字:长度 - 在本例中为17 - 和距离(或偏移量) - 在本例中为8293。
Huffman编码用代码替代实际数据。当数据为X时,Huffman代码为Y。如果替代比原始数据短,则显然有助于压缩。(在吉姆·凯瑞的电影Yes Man中,有一个反例,当Norm使用"Car"作为Carl的简称时,卡尔指出Carl已经很短了。)Huffman编码算法进行频率分析,并使用最短的替代方法替换最常出现的数据序列。
Deflate将这些组合起来,以便可以在LZ77反向引用上使用Huffman编码。各种DEFLATE / ZLIB压缩器上的策略选项只是告诉库如何权衡Huffman和LZ77。 通常意味着LZ77匹配停止于长度为5的位置。所以当文档说
使用(Filtered)处理由过滤器(或预测器)生成的数据,...过滤后的数据主要由具有某种随机分布的小值组成。
(摘自zlib手册
我的代码阅读表明它确实进行了LZ77匹配,但仅到五个或更少字节的序列。这就是文档所说的“小值”的含义。但数字5没有在文档中提到,所以不能保证该数字不会从版本到版本或从一个ZLIB / DEFLATE实现(如C版本和Java版本)改变。
  • HUFFMAN_ONLY 表示仅基于频率分析进行替换编码。 HUFFMAN_ONLY 很快,但对于大多数数据的压缩效果不是很好。除非您的字节值范围非常小(例如,如果您实际数据流中的字节仅占可能的 255 个值中的 20 个),或者在以大小为代价的压缩速度方面具有极端要求,否则 HUFFMAN_ONLY 将不是您想要的。

  • DEFAULT 将两种方法结合起来,这是作者预计对于大多数应用程序最有效的方式。


据我所知,在DEFLATE中没有仅使用LZ77的方法。也就是说,没有“LZ77_ONLY”策略。但是,您当然可以构建或获取自己的LZ77编码器,这将是“仅限LZ77”的。

请记住,策略永远不会影响压缩的正确性;它只影响压缩的操作和性能,无论是速度还是大小。


有其他方法可以调整压缩器。其中一种方法是设置LZ77滑动窗口的大小。在C库中,可以使用“窗口位”选项来指定此选项。如果您了解LZ77,则知道较小的窗口意味着较少的向后搜索,这意味着更快的压缩,但代价是会错过一些匹配。在进行压缩时,这通常是更有效的调节旋钮。


重点是,在80%的情况下,您不需要调整策略。您可能有兴趣调整窗口位,只是为了看看会发生什么。但只有在您的应用程序中完成所有其他必要的操作后才执行该操作。

参考资料:
DEFLATE是如何工作的,作者Antaeus Feldspar


您可以使用“Z_FIXED”策略来压缩LZ77而无需使用哈夫曼编码。 - user1629505

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接