gzip/bzip2/zlib/7z 算法对比
最近折腾压缩,想要将单个大文件进行压缩,对比了多种压缩算法,考虑到性价比,最后还是决定放弃压缩。测试的时候写了一个简单的 P y t h o n Python Python 脚本去测试。
from functools import wraps
import time
import os
import gzip
import bz2
import zipfile
import zlib
import os
def print_run_time(fun):
@wraps(fun)
def run_time(*args, **kwargs):
print("==================== Start... ====================")
t_s = time.clock()
res = fun(*args, **kwargs)
t_e = time.clock()
print("Total running time: %s s." % (str(t_e - t_s)))
print("==================== End. ========================")
return res
return run_time
div = 1024 * 1024 * 1024
raw_bag = "aaa.bag"
compressed_bag = {
"gzip": raw_bag + ".gz",
"bzip2": raw_bag + ".bz2",
"zlib": raw_bag + ".zlib",
"7z": raw_bag + ".7z"
}
def print_size_info(raw_bag_size, compression_bag_size):
compression_ratio = float(compression_bag_size) / raw_bag_size * 100
print("raw_bag size: %f Gb" % (float(raw_bag_size) / div))
print("compression_bag size: %f Gb" % (float(compression_bag_size) / div))
print("Compression ratio is %f %%" % compression_ratio)
def gzip_com():
with open(raw_bag, "rb") as in_put:
with gzip.open(compressed_bag.get("gzip"), "wb") as out_put:
# out_put.write(in_put.read())
data = in_put.read(1024)
while data:
out_put.write(data)
data = in_put.read(1024)
out_put.flush()
in_put.close()
out_put.close()
def bzip2_com():
with open(raw_bag, "rb") as in_put:
with bz2.BZ2File(compressed_bag.get("bzip2"), "wb") as out_put:
# out_put.write(in_put.read())
data = in_put.read(1024)
while data:
out_put.write(data)
data = in_put.read(1024)
in_put.close()
out_put.close()
def zip_com():
out_put = zipfile.ZipFile(compressed_bag.get("zip"), "w")
out_put.write(raw_bag)
out_put.close()
def zlib_com():
with open(raw_bag, "rb") as in_put:
with open(compressed_bag.get("zlib"), "wb") as out_put:
zlib_ = zlib.compressobj(9)
data = in_put.read(1024)
while data:
out_put.write(zlib_.compress(data))
data = in_put.read(1024)
out_put.write(zlib_.flush())
# out_put.write(zlib_.compress(in_put.read()))
in_put.close()
out_put.close()
def seven_zip_com():
cmd = "7za a " + compressed_bag.get("7z") + " " + raw_bag
print(cmd)
os.system(cmd)
print("OK!")
compression = {
"gzip": gzip_com,
"bzip2": bzip2_com,
"zlib": zlib_com,
"7z": seven_zip_com
}
@print_run_time
def compression_test(com):
print("%s_test..." % com)
compression.get(com)()
print_size_info(os.path.getsize(raw_bag), os.path.getsize(compressed_bag.get(com)))
# compression_test("gzip")
# compression_test("bzip2")
# compression_test("zlib")
compression_test("7z")
经过多次测试,对一个 5 s 5s 5s 将近 1 G 1G 1G 大小的 b a g bag bag 包进行来压缩,其中 g z i p / z l i b gzip/zlib gzip/zlib 压缩率在 85 % 85\% 85% 左右,时间大概花了 25 s 25s 25s, b z i p 2 bzip2 bzip2 压缩率略高,在 75 % 75\% 75% 的样子,但是时间成本花了 60 s 60s 60s,而 7 z 7z 7z 压缩率最高,达到 67 % 67\% 67%,但是时间高达两分半。
又对一个 60 s 60s 60s 将近 10 G 10G 10G 的 b a g bag bag 进行压缩,压缩比与上述接近, g z i p / z l i b gzip/zlib gzip/zlib 的时间成本差不多 300 s 300s 300s, b z i p 2 bzip2 bzip2 的时间成本高达 650 s 650s 650s,至于 7 z 7z 7z,就不用测了,时间更高,不浪费时间了。
目前 7 z 7z 7z 是公认压缩率最高的,但是和 l z m a lzma lzma 一样,都是极度消耗资源的;最快的算法应该是 l z 4 lz4 lz4,但是压缩率肯定要低很多,还没有来得及测试;不过像我这样的需求(压缩单个大文件),可能 l z o lzo lzo 也不错,因为他比较适合这样的场景,单个文件越大,效果越好,有待测试。
目前还有一种想法就是,对 b a g bag bag 包中的一部分数据进行压缩,也许有损压缩也是可以接受的。 b a g bag bag 中主要的数据是图片和点云,点云不能有损压缩,但是图片也许可以。然而由于不能在线压缩(录制 b a g bag bag 时就进行压缩,过分消耗资源),所以暂时也先不考虑了。
太感人了,最后的测试结果,竟然是放弃压缩。如果大佬们有更好的压缩方案,请指教。