Java Deflater 策略 - DEFAULT_STRATEGY、FILTERED 和 HUFFMAN_ONLY

标签 java compression gzip deflate

我试图在 gzip 压缩 Java webapp 响应时在性能和压缩程度之间找到平衡。

在查看 Deflater 类时,我可以设置一个级别和一个策略。级别是不言自明的 - BEST_SPEEDBEST_COMPRESSION .

我不确定这些策略 - DEFAULT_STRATEGY , FILTEREDHUFFMAN_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 时,霍夫曼代码显示 Y。这显然只有在替代值比原始值短时才有助于压缩。 (反例是在 Jim Carrey 的电影 Yes Man 中,当时 Norm 使用“Car”作为 Carl 的简称。Carl 指出 Carl 已经很短了。)霍夫曼编码算法进行频率分析,并使用最常出现的数据序列的最短替代品。


  • Deflate 结合了这些,因此可以在 LZ77 反向引用上使用霍夫曼代码。各种 DEFLATE/ZLIB 压缩器的策略选项只是告诉库霍夫曼与 LZ77 的权重。
  • FILTERED通常意味着 LZ77 匹配在长度为 5 处停止。所以当文档说

    Use (Filtered) for data produced by a filter (or predictor), ... Filtered data consists mostly of small values with a somewhat random distribution.



    (来自 the zlib man page)
    ...我对代码的阅读表明它进行 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% 的情况,您不需要调整策略。您可能对摆弄窗口位感兴趣,只是想看看会发生什么。但只有在您完成了您需要在应用程序中执行的所有其他操作后,才能执行此操作。

    引用:
    How DEFLATE works, by Antaeus Feldspar

    关于Java Deflater 策略 - DEFAULT_STRATEGY、FILTERED 和 HUFFMAN_ONLY,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2527146/

    相关文章:

    JavaFX:将 Pane View 保存到图像

    java - 将按钮添加到选项卡中

    java - 如何从 Activity 中执行在已启动服务上定义的方法并取回结果?

    java - 将文件上传到 google appengine 的代码片段中生成错误

    .net - PowerShell:使用 System.IO. Compression.FileSystem 将文件移动到 zip

    c++ - 是否有可用于 GZIP 的测试 vector ?

    java - 如何在 JAX-RS 中提供已压缩的内容?

    hadoop - 如何插入具有 Parquet 文件格式和 SNAPPY 压缩的配置单元表?

    javascript - 使用 Google Closure Compiler Application 在一个文件中压缩所有文件 .js

    php - 使用 GZip 压缩输出