4. 常见压缩算法详解
在 OTA 镜像压缩工程中,算法选型直接决定了三件事:镜像包体积、端侧解压耗时、以及服务端压缩吞吐。很多团队只盯着“压缩率”一个指标,结果在低端车机或 IoT 设备上出现解压卡顿、CPU 飙高、升级窗口超时。本节把 DEFLATE、LZ4、Zstandard、Brotli、Gzip 放在同一张“压缩率—速度—内存”坐标系里讲清楚,帮助你在不同镜像类型和硬件档位上做出可落地的选择。
一、核心原理:五类算法其实分属两条技术路线
这五种算法并不是并列关系,而是“字典压缩 + 熵编码”组合方式不同。理解它们的家族关系,比死记参数更重要。
- LZ4:纯 LZ77 系字典压缩,只做“匹配—复制”,几乎不做熵编码。它的设计目标是极致解压速度,压缩率通常最低,但解压可达 GB/s 级。
- DEFLATE:LZ77 字典 + 霍夫曼熵编码,是 Gzip、ZIP、PNG 的底层算法。压缩率中等,解压速度中等,兼容性最好。
- Gzip:严格说是“DEFLATE + gzip 容器头/尾(CRC32、ISIZE)”,算法内核就是 DEFLATE,因此压缩率与 DEFLATE 基本一致,只是多了封装开销。
- Zstandard(Zstd):LZ77 系 + 有限状态熵(FSE)/霍夫曼,支持 1~22 级压缩,且提供“字典训练”能力。它在压缩率与速度之间提供了连续可调的曲线。
- Brotli:LZ77 变体 + 上下文建模 + 静态字典(内置常见 Web/文本片段),压缩率最高,但压缩慢、解压内存占用偏高,适合静态资源而非高频小包。
二、算法性能对比:一张表看清选型边界
下表以典型 OTA 镜像(混合二进制 + 资源文件,约 500MB)为参考,数值为工程经验区间,实际会随数据熵和硬件变化。
| 算法 | 压缩率(相对原始) | 压缩速度 | 解压速度 | 解压内存 | 典型适用场景 |
|---|---|---|---|---|---|
| LZ4 | 约 50%~60% | 极快 | 极快(GB/s 级) | 极低 | 端侧实时解压、低端设备、差分补丁 |
| DEFLATE | 约 30%~40% | 中等 | 中等 | 低 | 兼容性优先、ZIP/PNG 生态 |
| Gzip | 约 30%~40% | 中等 | 中等 | 低 | HTTP 传输、日志归档、通用分发 |
| Zstandard | 约 25%~35%(可调) | 快~中等(级别可调) | 快 | 中低 | OTA 主镜像、需平衡体积与耗时 |
| Brotli | 约 20%~30% | 慢 | 中等偏慢 | 中高 | 静态资源、Web 包、一次性下载 |
从表中可以看出:如果端侧 CPU 弱、升级窗口紧,LZ4 是安全牌;如果带宽是瓶颈、端侧算力充足,Brotli 或高等级 Zstd 更划算;Gzip 则是“哪里都能用,但哪里都不极致”的兜底方案。
三、方法流程:OTA 镜像压缩的推荐流水线
实际工程中很少只用一种算法,而是按“镜像分层 + 算法分级”组合。下面是一条经过验证的流水线:
- 镜像分层:将系统镜像拆分为 boot、system、vendor、资源包等独立块,便于差异化压缩。
- 熵评估:对每层计算熵值,已压缩数据(如 JPEG、APK)不再二次压缩,避免负收益。
- 算法匹配:高熵块用 LZ4 或 store,低熵文本/代码块用 Zstd 高等级或 Brotli。
- 字典训练:对 Zstd 使用历史镜像样本训练字典,小文件压缩率可提升 10%~20%。
- 并行压缩:Zstd 支持多线程,服务端按核数并行,缩短打包时间。
- 校验与回滚:压缩后写入 CRC32/SHA256,端侧解压失败可回退到原始分区。
# Zstd 多线程压缩示例(服务端打包)
zstd -T8 -19 --long=27 -o system.img.zst system.img
# LZ4 高速压缩(端侧友好)
lz4 -9 -B4 --content-size system.img system.img.lz4
# Gzip 兼容模式
gzip -9 -k system.img
# 解压耗时对比(端侧实测脚本片段)
time zstd -d system.img.zst -o /dev/block/by-name/system
time lz4 -d system.img.lz4 -o /dev/block/by-name/system
四、案例与场景:不同硬件档位的选型实践
场景 A:低端车机(4 核 A53,2GB RAM)。升级包 800MB,要求 3 分钟内完成。实测 Brotli 解压耗时超过 90 秒且内存峰值高,Zstd-19 解压约 35 秒,LZ4 仅 12 秒但包体增大到 480MB。最终采用“Zstd-9 + LZ4 混合”:核心分区 Zstd,资源分区 LZ4,整体升级时间控制在 70 秒内。
场景 B:云端 OTA 分发(带宽敏感)。镜像以文本配置和脚本为主,Brotli 将包体从 320MB 压到 78MB,虽然服务端压缩耗时增加,但 CDN 流量成本下降约 60%,端侧为高性能网关,解压耗时可接受。
场景 C:差分升级补丁。补丁本身很小(几 MB),但数量多、频次高。使用 Zstd 字典训练后,平均补丁体积再降 15%,且解压速度满足秒级安装。
五、误区与复盘:三个常见踩坑点
- 误区一:压缩率越高越好。 Brotli-11 压缩率确实最低,但服务端压缩可能耗时数十分钟,且端侧解压内存翻倍,低端设备直接 OOM。
- 误区二:所有数据都值得压缩。 已压缩的 JPEG、MP4、APK 再压缩往往体积不变甚至变大,应先做熵检测,高熵块直接 store。
- 误区三:忽略解压内存。 Zstd 高等级和 Brotli 的解压窗口较大,在内存受限的 MCU 或低端 SoC 上必须实测峰值内存,而不是只看压缩率。
总结来看,OTA 镜像压缩没有“最好”的算法,只有“最匹配当前硬件与网络约束”的组合。把 LZ4 当作速度底线,把 Zstd 当作主力可调引擎,把 Brotli 留给带宽敏感且端侧算力充足的场景,把 Gzip/DEFLATE 作为兼容兜底,就能在体积、耗时与稳定性之间取得可控的平衡。