在尝试压缩Java webapp响应时,我试图在性能和压缩程度之间找到平衡。
在查看Deflater类时,我可以设置一个级别和一个策略。这些级别不言自明 - BEST_SPEED
到BEST_COMPRESSION
。
我不确定策略 - DEFAULT_STRATEGY
,FILTERED
和HUFFMAN_ONLY
我可以从Javadoc中获得一些意义,但我想知道是否有人在他们的应用程序中使用了特定策略,并且您是否看到在性能/压缩程度方面存在任何差异。
答案 0 :(得分:14)
我相信Java Deflater中提到的策略选项起源于ZLIB和(RFC 1950)和DEFLATE(1951)的zlib(C)实现。它们几乎存在于实现DEFLATE的所有压缩库中。
要了解它们的含义,您需要了解一点DEFLATE。压缩算法结合了LZ77和霍夫曼编码。基础是:
LZ77压缩通过查找重复的数据序列来工作。实现通常使用介于1k和32k之间的“滑动窗口”,以跟踪之前的数据。对于原始数据中的任何重复,LZ77压缩不是在输出中插入重复数据,而是插入“反向引用”。想象一下后面的引用说“在这里,插入你看到的8293字节前的相同数据,为17个字节”。 back-ref被编码为这对数字:长度 - 在这种情况下为17 - 和距离(或偏移) - 在这种情况下为8293.
霍夫曼编码代替实际数据的代码。当数据表示X时,霍夫曼代码表示Y.这显然只有在替代品短于原始数据时才有助于压缩。 (一个反例是在Jim Carrey电影Yes Man中,当Norm使用“Car”作为Carl的短名时.Carl指出Carl已经很短了。)Huffman编码算法进行频率分析,使用最常出现的数据序列的最短替代。
Deflate结合了这些,因此可以在LZ77反向参考上使用霍夫曼代码。各种DEFLATE / ZLIB压缩机的策略选项只是告诉图书馆对Huffman和LZ77的重量是多少。
FILTERED
通常意味着LZ77匹配停止在5的长度。所以当文档说
对过滤器(或预测器)生成的数据使用(过滤),...过滤后的数据主要由具有某种随机分布的小值组成。
(来自the zlib man page)
...我对代码的读取表明它与LZ77匹配,但只能达到5个或更少字节的序列。这就是我认为“小价值”所指的文档意味着什么。但是文档中没有提到数字5,因此无法保证数字不会从rev更改为rev,也不能保证从ZLIB / DEFLATE的一个实现更改为另一个(如C版本和Java版本)。
HUFFMAN_ONLY
说,只根据频率分析进行替换代码。 HUFFMAN_ONLY
非常快,但对大多数数据的压缩效果不是很高。除非您的字节值范围非常小(例如,如果实际数据流中的字节只占用了可能的255个值中的20个中的一个),或者以压缩大小为代价对压缩速度有极高的要求,{{1}不会是你想要的。
HUFFMAN_ONLY
将两者结合起来,就像作者预期的那样,它对大多数应用程序最有效。
据我所知,在DEFLATE内,没有办法只做LZ77。没有DEFAULT
策略。但是当然你可以建造或购买你自己的LZ77编码器,这将只是“LZ77”。
请记住,策略永远不会影响压缩的正确性;它只影响它的运行和运行,无论是速度还是尺寸。
还有其他方法可以调整压缩器。一种是设置LZ77滑动窗口的大小。在C库中,这是通过“窗口位”选项指定的。如果您了解LZ77,那么您知道较小的窗口意味着较少的搜索,这意味着更快的压缩,代价是错过了一些匹配。这通常是压缩时更有效的旋钮。
最重要的是,对于80%的情况,您并不关心调整策略。您可能对摆弄窗口位感兴趣,只是为了看看会发生什么。但只有当你完成了在应用程序中需要做的其他事情时才这样做。