2 分钟阅读

前言

最近在折腾嵌入式环境和交叉编译时,有一次发现这个问题:

为什么有些压缩文件解压得这么慢?

尤其是在 Windows 上解压 GNU 源码的 .tar.xz 时,进度条几乎冻结。这种体验几乎人人都遇到过,但大多数时候我们只会骂一句“这包有病”,然后继续等。

那么,不同压缩格式,究竟在“换”什么?

总览

首先,压缩和解压缩的根本是:

压缩 = 用计算时间换空间
解压 = 用空间结构换计算

文件压缩的三种境界

先从zip文件入手:Level 1 LZ家族

代表格式:zip, gzip, zstd

它们的核心思想是:

“刚刚出现过的字符串,再出现就不写一遍了”

例如:

abcdefg ... abcdefg

第二次出现时:

(向后 123 字节,长度 7)

影响结果:

压缩率:中等
速度:很快
内存占用:低

这就是为什么:

  • .zip 解压快

  • 体积一般

统计手段 Level 2:Huffman家族

代表格式:gzip, zstd, bz2

在 Level 1 基础上:

出现多的字符 → 用短编码
出现少的字符 → 用长编码

就像摩斯电码:

E → .
Q → --.-

代价:

要先扫一遍数据  ->  建统计表

这一步开始明显吃 CPU

我用数学压你 Level 3:LZMA / xz

代表:.xz

这里开始“变态”了。

它会做什么?

非常大的滑动窗口(几十 MB)
非常复杂的概率模型
非常深的回溯搜索

本质上在做:

“在尽可能大的历史范围内,
找到最优的重复表示方式”

结果就是:

压缩率:极高(Qt 源码这种文本天堂)
解压速度:慢
内存:吃得狠

为什么 .xz 解压这么慢?

这是很多人第一次解源码都会骂的点。

真实原因不是“算法慢”

而是:

解压过程本身就是在执行一个巨大的概率解码器

它在干三件事:

按 bit 读(不是字节)
       ↓
动态更新概率模型
       ↓
不停地做分支预测

这三件事对 CPU 来说都很不友好。

但是优点是可以做到对大量重复文本的极致压缩。

这在过去,对节省网络带宽和存储容量是神助,不知道节省世界多少钱和时间。

文件压缩的根本哲学

.xz 使用的是 LZMA 系列算法,它的风格可以概括为一句话:

我宁愿算到天荒地老,也要把你压到最小。

.zip 的哲学几乎是另一个极端:

够用就行,别太聪明。

不同压缩格式,其实是不同年代的选择

.tar.gz
老工程师的安全牌
稳定、快、压缩率尚可

.zip
普世通用格式
为兼容性而生

.tar.bz2
早期追求更高压缩率的尝试
现在逐渐被淘汰

.tar.xz
理论派、极致派
带宽比时间贵的时代产物

.tar.zst
现代工程折中方案
在速度和压缩率之间重新平衡

不同历史阶段的工程答案并存,在不同历史时刻,给出了不同历史答卷。压缩文件的繁荣也是社会的繁荣。

所以,慢不代表差。慢也是工程师的浪漫。

等待的时间,可以拿来干别的事情,比如喝杯咖啡、看看风景、给爱人发条消息,或者拿来写一篇博客。

也许科技发展了,带宽和存储不再是瓶颈,你的等待也变成了多此一举,但是别忘了,这个世界就是靠这些tar.xz建设起来的。至少在过去,它不是在浪费你的时间,而是在为另一个维度节省成本。

就当是体谅千千万万工程师好了,说不定你的等待,也是他们为了让你不要忘记他们的小心思。

留下评论