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