几周前,我正在处理一个相当大的.tar.gz文件,我想知道文件的顺序对过程有什么影响。我对压缩不是很了解,但我知道gzip使用滑动窗口来寻找机会压缩重复的文本块。如果你给它高度重复的文本,它会做得很好,如果你给它随机的数据,它可能会给你一个比你开始时更大的文件。因此,重新排序文件似乎很重要。
这个想法似乎很明显,其他人可能已经研究过了,但我决定花几个小时摆弄代码,而不是调查它是否已经实现了。1个。
我无缘无故地使用了我的项目StringMatching。我从GitHub克隆了Commit 0a4ad368d25c5af7d3d751f9e903abc8ae792dae。我决定删除.git目录,因为我认为这样更容易猜测进程是如何处理文本文件的。结果.tar为337920字节,.tar.gz为45768字节。
代码在GitHub上。对于涉及一些随机性的尝试,我运行了10次,并捕获了最好的、最差的和平均的结果。我用最好的结果做了比较,因为如果你想使用这些技术,你可以做多次运行,然后选择最好的一个。
混洗文件:我混洗了所有找到的文件的列表,然后将它们添加到存档中。
最常见的令牌:我应用了一个朴素的正则表达式将Java代码分割成片段,这些片段有时可能与Java语法中的令牌相对应,然后根据文件最常用的令牌对文件进行排序。事后看来,这并不令人惊讶,这会带来可怕的结果。也许return是任意Java文件中最常见的令牌。
在目录中混洗文件:与#1相同,不同之处在于我们只在一个目录内混洗,将该目录中的所有文件放在一起。
按大小排序文件:这似乎很荒谬。它最终表现良好的事实可能只是运气,尽管您可以想象较大的代码片段在结构上有相似之处。
使用默认顺序的脚本:我使用与其他尝试相同的过程,而没有更改遍历目录返回的文件顺序。我怀疑目录顺序与tar使用的目录顺序不同,导致空间增加,但我没有检查。
Tar-czvf:基线实现。与其他几次尝试相比,它做得很好,这是有道理的。同一包中的文件可能使用许多相同的导入、类型和方法。
交换相邻文件一种冒泡排序的LIK算法。从文件的自然顺序开始,我们尝试交换文件,然后重新创建gzip存档。如果结果小于之前的最佳结果,我们将保留交换,并尝试将移动的元素与其前面的元素交换。
在目录内混洗后交换相邻文件:应用与5中相同的算法,但要事先在目录内混洗文件,如#3所示。
毫无头绪。很难想象这些实现有什么好处--最佳结果需要至少对n文件归档的tar-czvf执行O(N)次调用。Google的zopfli算法花费了大量的CPU时间来换取压缩文件大小的适度改善,因此更好的实现可能会很有趣。最后,我在一个库上做了一个实验,因此现实世界的结果可能完全不同。
然后我把我的结果放在一边几个星期,然后把它们写出来。↩