133 MiB 访问日志压缩实测:zstd -19 慢 175 倍,每秒只省下 48 KiB
一次很常见的选型纠结
归档日志、打包 CI 产物、做镜像层压缩时,总会遇到同一个问题:压缩等级调多少?很多团队的做法是把等级直接拧到最大,理由是"反正是一次性开销,小一点总没坏处"。
本文用一台 4 核机器、一份 133.4 MiB 的真实形态访问日志(nginx 默认格式、带 UA 与 rt/upstream 字段),把 gzip / pigz / zstd / xz 的常用档位全跑了一遍。时间与体积来自同一轮测量,输入文件已预热进 page cache,所以下面比的是纯 CPU 成本,不是磁盘速度。
实测数据
| 工具与档位 | 耗时 | 压缩后 | 占原始 | 吞吐 |
|---|---|---|---|---|
| gzip -1 | 1.18 s | 22.82 MiB | 17.1% | 113 MiB/s |
| gzip -6 | 2.92 s | 17.71 MiB | 13.3% | 46 MiB/s |
| gzip -9 | 6.09 s | 17.11 MiB | 12.8% | 22 MiB/s |
| pigz -6 -p4 | 0.96 s | 17.74 MiB | 13.3% | 139 MiB/s |
| zstd -1 | 0.45 s | 19.97 MiB | 15.0% | 297 MiB/s |
| zstd -3 | 0.72 s | 20.16 MiB | 15.1% | 185 MiB/s |
| zstd -3 -T4 | 0.30 s | 20.16 MiB | 15.1% | 440 MiB/s |
| zstd -19 | 126.20 s | 14.22 MiB | 10.7% | 1.1 MiB/s |
| xz -1 | 7.47 s | 17.65 MiB | 13.2% | 18 MiB/s |
| xz -6 -T4 | 36.31 s | 13.96 MiB | 10.5% | 3.7 MiB/s |
结论一:档位不是线性的,gzip -6 → -9 是最亏的一档
从 -6 到 -9,CPU 时间翻倍(2.92 s → 6.09 s),体积只从 17.71 MiB 降到 17.11 MiB,绝对值省下 0.6 MiB,相对只小 3.4%。换句话说,多花的那 3 秒买到了 0.6 MiB。如果这份日志每天要压一次、保留 30 天,一年下来省 200 MiB 左右,而多耗的 CPU 时间约 19 分钟——不算灾难,但也没多少价值。
真正便宜的是低档位区间:gzip -1 用 1/5 的时间拿到 17.1% 的体积,压缩率只比 -9 差 4.3 个百分点。
结论二:多线程比调档位划算得多
同一档位 gzip -6,用 pigz -6 -p4 跑,体积只比单线程 gzip 大 0.17%(17.74 vs 17.71 MiB,是并行分块带来的边界损耗),时间从 2.92 s 掉到 0.96 s,快 3 倍。
在 4 核机器上继续调 gzip 的等级,本质是在用单核算力换百分比;而开多线程是在用闲置的算力换整块时间。zstd -3 -T4 更极端:0.30 s,440 MiB/s,比单线程 gzip -1 快 4 倍、体积还小 14%。
一个常被忽略的细节:gzip/zstd/xz 都支持多线程参数,但很多脚本里写的还是裸 gzip -9。如果你在 CI 里压缩产物,把命令换成 pigz -6 -p$(nproc) 通常就是一行改动、三倍收益。
结论三:极端档位的边际收益会崩掉
zstd -19 花了 126 秒,比 zstd -3 的 0.72 秒慢 175 倍,体积小 29.5%(20.16 → 14.22 MiB)。折算下来,多花的每一秒只省回约 48 KiB。
更值得注意的是对照:xz -6 -T4 只用 36 秒就压到 13.96 MiB,比 zstd -19 更小、还快 3.5 倍。也就是说,如果目标真的是"压到最小",多线程 xz 比单线程 zstd -19 更值得考虑(代价是 xz 的内存占用和解压速度,见下一节)。
解压侧:读路径比写路径更重要
压缩只发生一次,解压可能发生很多次。同一份数据解压到 /dev/null:
- gunzip(gzip -6 产物):534 ms,250 MiB/s
- zstd -dc(-3 产物):223 ms,598 MiB/s
- zstd -dc(-19 产物):260 ms,513 MiB/s
- unxz -T4(xz -6 产物):425 ms,314 MiB/s
zstd 的解压速度是 gzip 的 2.4 倍左右,而且几乎不受压缩档位影响。对于"每天压一次、每次发布都要解开"的场景,这个差距比压缩体积重要得多。
落地建议
- 热数据、在线传输、容器层:
zstd -3 -T0,够快也够小。 - 只认 .gz 的老工具链:
pigz -6 -p$(nproc),一行改动换三倍时间。 - 冷归档、一年动一次:
xz -6 -T0(或zstd --ultra -19 --long=27),但请先确认机器内存扛得住。 - 别再用裸
gzip -9当默认值:它的性价比在这份数据里是最差的一档。 - 决策时把"解压次数"算进去:一次性归档看体积,反复读取看解压吞吐。
复现很简单,把 access.log 换成你自己的日志:
for lv in 1 6 9; do
/usr/bin/time -f "gzip -$lv %es" gzip -$lv -c access.log | wc -c
done
/usr/bin/time -f "pigz -6 %es" pigz -6 -p4 -c access.log | wc -c
/usr/bin/time -f "zstd -3 -T4 %es" zstd -3 -T4 -c access.log | wc -c
压缩档位不是"越大越好",而是一条边际收益递减的曲线。先确认你付的是 CPU 还是时间,再决定拧到哪一格。
- 点赞
- 收藏
- 关注作者
评论(0)