- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
文件位于:“意外效率部门”。
前 9000 万个数字占用约 761MB,输出为:
seq 90000000
根据 man parallel
,它可以加速 gzip
的归档大文件,方法是将输入切碎,并使用不同的 CPU 来压缩 block 。因此,尽管 gzip
是单线程,但这项技术使其成为多线程:
seq 90000000 | parallel --pipe --recend '' -k gzip -9 >bigfile.gz
在 Intel Core i3-2330M (4) @ 2.2GHz 上耗时 46 秒。
将其通过管道传输到普通的旧 gzip
:
seq 90000000 | gzip -9 > bigfile2.gz
在同一个 CPU 上耗时 80 秒。现在是惊喜:
ls -log bigfile*.gz
输出:
-rw-rw-r-- 1 200016306 Jul 3 17:27 bigfile.gz
-rw-rw-r-- 1 200381681 Jul 3 17:30 bigfile2.gz
300K 更大?那看起来不对劲。首先,我检查了 zdiff
文件是否具有相同的内容——是的,相同。我原以为任何压缩器在处理连续数据流时会比分 block 压缩器做得更好。为什么 bigfile2.gz
不小于 bigfile.gz
?
最佳答案
原因是对于这个特殊的、相当不寻常的输入,较小的放气 block 比较大的放气 block 更好。默认情况下,gzip
使用较大的 deflate block ,因为它最适合普通输入数据。 parallel
命令通过每 1 MB 分解输入来强制使用一些较小的压缩 block ,从而产生较小的增益。尽管大多数 block 的大小仍然相同。
通过使用 zlib 为每个 block 设置较小的 block 大小可以做得更好deflateInit2()
中的 memLevel
参数。在这里,我每次都在单个线程中压缩相同的输出,使用从 9 到 2 的 memLevel
值,其中较小的 memLevel
是较小的放气 block 大小(请注意 zlib在默认级别比您的 gzip
好一点):
此数据的最佳 memLevel
结果为 4,压缩后的数据比默认 memLevel
8 小 12 MB (9%)。对于 memLevel
8,deflate block 大小为 16383 个符号,而对于 memLevel
4,deflate block 大小为 1023 个符号。一个符号是文字字节或匹配项。
改进来自输入的极其规则的性质,导致匹配和文字命令的规则序列。 block 大小越小,出现的这种不同的命令就越少,然后需要更少的比特来对它们中的每一个进行编码。这对于 memLevel
3 仍然适用,但到那时每个 deflate block 开头的代码描述的开销抵消了更少不同代码的改进。
zopfli
是一个 deflate 压缩器,可以优化 block 大小和所选命令,并设法将其压缩到 100,656,812 字节。虽然花了三个半小时! zopfli
被调用 pigz
使用压缩级别 11。
关于linux - 为什么 gnu 并行分块会提高 gzip 的压缩大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38178734/
我是一名优秀的程序员,十分优秀!