最近折腾压缩,想要将单个大文件进行压缩,对比了多种压缩算法,考虑到性价比,最后还是决定放弃压缩。测试的时候写了一个简单的 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 时就进行压缩,过分消耗资源),所以暂时也先不考虑了。

太感人了,最后的测试结果,竟然是放弃压缩。如果大佬们有更好的压缩方案,请指教。