【问题标题】:How does gzip compression rate change when streaming data?流式传输数据时 gzip 压缩率如何变化?
【发布时间】:2013-11-11 02:29:33
【问题描述】:

我一直试图在 HTTP 流连接(SSE 和各种彗星技术)的上下文中理解 gzip 算法。我用这些文件大小测试了一些替代的数据表示:

40 csv.txt
63 json-short.txt
80 json-readable.txt

27 rawbin.txt

46 sse.csv.txt
69 sse.json-short.txt
86 sse.json-readable.txt

当使用gzip -9v 压缩时,我得到:

csv.txt:     25.0%
json-readable.txt:   16.2%
json-short.txt:  20.6%
rawbin.txt:  18.5%
sse.csv.txt:     25.0%
sse.json-readable.txt:   15.1%
sse.json-short.txt:  18.8%

这些压缩率不是很好,但也与预期相反:越冗长的 JSON 格式似乎压缩得越差。

我的问题是:随着越来越多的数据被流式传输,压缩是否会变得更好?它是否动态地和隐式地了解哪些位是脚手架,哪些位是可变数据?如果是学习算法,是否存在停止学习的点,还是理论上总是适应数据流?如果是这样,是否对最近的数据给予额外的重视?

我做了一个粗略的测试,将 sse.json-readable.txt 的 25 个 cat-ing 放入一个文件中。 Gzip 然后给了我 95.7% 的压缩率。但我将其描述为粗糙有两个原因。首先,每一行数据都是相同的,而在现实数据中,数字和时间戳会略有不同,只有脚手架是相同的。第二个原因是 gzip 被赋予一个文件:gzip 算法是对数据进行预扫描以学习它,还是在文件中跳转?如果是这样,这些结果将不适用于 Apache 流数据(因为它在看到第二行之前已经压缩并发送了第一行数据)。

作为次要问题,我可以假设时间不是一个因素吗?例如。假设不涉及套接字重新连接,则每行数据之间可能会有 1 秒的间隔,或者 60 秒的间隔。

关于 gzip 工作原理的有用参考:http://www.infinitepartitions.com/art001.html

(顺便说一句,我目前的理解是流式传输时的压缩将仅基于对第一个数据块的分析;所以我想知道是否可以通过发送几行虚拟数据来获得更好的压缩,让它有机会学习更好的压缩?!?)

http://svn.apache.org/repos/asf/httpd/httpd/trunk/modules/filters/mod_deflate.c 15 是 32KB。

http://www.zlib.net/zlib_how.html http://www.zlib.net/zlib_tech.html

更新:有用的链接

这里是 Apache 模块代码: http://svn.apache.org/repos/asf/httpd/httpd/trunk/modules/filters/mod_deflate.c

15 的窗口大小是 Mark Adler 在回答中提到的 32KB 窗口的原因。

以下是一些有助于理解 Apache 代码的页面: http://www.zlib.net/zlib_how.html http://www.zlib.net/zlib_tech.html


这里是上面的测试文件,以防万一:

csv.txt

2013-03-29 03:15:24,EUR/USD,1.303,1.304

json-short.txt

{"t":"2013-03-29 06:09:03","s":"EUR\/USD","b":1.303,"a":1.304}

json-readable.txt

{"timestamp":"2013-03-29 06:09:03","symbol":"EUR\/USD","bid":1.303,"ask":1.304}

sse.csv.txt

data:2013-03-29 03:15:24,EUR/USD,1.303,1.304

sse.json-short.txt

data:{"t":"2013-03-29 06:09:03","s":"EUR\/USD","b":1.303,"a":1.304}

sse.json-readable.txt

data:{"timestamp":"2013-03-29 06:09:03","symbol":"EUR\/USD","bid":1.303,"ask":1.304}

注意:sse.* 版本以两个 LF 结尾,其他版本以一个 LF 结尾。

rawbin.txt 是用这个 PHP 脚本制作的:

$s=pack("la7dd",time(),"USD/JPY",1.303,1.304);
file_put_contents("rawbin.txt",$s);

【问题讨论】:

    标签: apache gzip comet server-sent-events


    【解决方案1】:

    gzip 使用最后 32K 数据的滑动窗口来搜索匹配的字符串。它将累积 16K 文字和匹配的字符串,这可能会返回其中一些窗口,以便生成带有一组霍夫曼代码的块。就像 gzip 看起来一样,它永远不会“跳来跳去”,而只是保持一个滑动历史,一旦旧数据从后端丢失,它就会忘记。

    zlib(不是 gzip)有一种方法可以提供“启动”字典,在压缩实际数据的前 32K 时,最多可以使用最多 32K 的数据来匹配字符串。这对于压缩少量数据(例如远小于 32K)很有用,有时非常有用。没有那个 zlib 或 gzip 在压缩短字符串时会做得很差。他们确实需要几倍于 32K 的数据才能滚动。

    对于您正在测试的极短文件,您得到的是扩展,而不是压缩。

    【讨论】:

    • 谢谢马克。一旦我了解了滑动窗口的想法,我就去寻找,并用一些有用的链接更新了我的问题。我能否确认流开始时会很糟糕,但很快会变得更好,并且在将 32KB(未压缩)数据发送到客户端后达到最大压缩率?
    • 类似的东西。第一个 deflate 块通常有大约 64K 到 128K 的未压缩字节。 next 块应该具有代表性的压缩比。因此,您通常需要等待超过 32K 才能看到更稳定的状态行为。这一切都假设数据是相对同质的。
    猜你喜欢
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 2016-10-11
    • 1970-01-01
    相关资源
    最近更新 更多