本文来自 trifectatech.org/blog/bzip2-...
今天我们发布了 bzip2
版本 0.6.0,它默认使用我们用 Rust 实现的 bzip2 算法库 ------ libbz2-rs-sys
。这意味着 bzip2 crate 现在更快、更容易进行交叉编译。
如果你有 C 项目,也可以将 libbz2-rs-sys
构建为 C 动态库,以便受益于这些改进。
为什么要做这件事?
为什么要为一个 90 年代的算法费心投入?虽然 bzip2 现在用途不广,但很多协议和库仍需支持它,以符合规范要求。因此很多项目的依赖树深处仍然依赖 bzip2。
我们借助从 zlib-rs
积累的经验,对 bzip2 实现进行了现代化重构。
我们曾在《使用 c2rust 翻译 bzip2》中写过 libbz2-rs-sys
的实现细节。现在让我们看看这些工作的实际收益。
性能提升
我们的 Rust 实现通常比 C 实现更快。虽然在某些场景下只是持平,但我们尚未遇到明显更慢的情况。
在压缩方面,我们快了不少。对于 bzip2 来说,level 表示使用的工作内存量,对性能影响不大。在 sample3.ref
上,level 1 就已经分配了比文件还大的内存,因此更高等级几乎无意义。
文件名 | C(CPU 周期) | Rust(CPU 周期) | 性能提升 |
---|---|---|---|
sample3.ref(level 1) | 38.51M ± 77.03K | 33.53M ± 90.52K | -14.87% |
silesia-small.tar(level 1) | 3.43G ± 2.06M | 3.00G ± 6.31M | -14.30% |
silesia-small.tar(level 9) | 3.47G ± 4.86M | 3.17G ± 4.43M | -9.66% |
在解压缩方面,虽然差异更分散,但总体上依然有显著提速:
文件名 | C(CPU 周期) | Rust(CPU 周期) | 性能提升 |
---|---|---|---|
sample3.bz2 | 2.53M ± 30.08K | 2.42M ± 8.95K | -4.48% |
sample1.bz2 | 9.63M ± 40.44K | 8.86M ± 10.64K | -8.63% |
sample2.bz2 | 20.47M ± 55.28K | 19.02M ± 36.13K | -7.67% |
dancing-color.ps.bz2 | 87.46M ± 481.02K | 83.16M ± 548.86K | -5.17% |
re2-exhaustive.txt.bz2 | 1.89G ± 12.29M | 1.76G ± 12.64M | -7.65% |
zip64support.tar.bz2 | 2.32G ± 12.09M | 2.11G ± 15.42M | -10.00% |
注意事项 :在我们的 macOS 基准机上,解压性能偶尔会出现较低的数值。我们尚未找到具体原因;在 macOS 上进行细致性能分析相当困难(例如找不到像 perf
这样的性能追踪工具可用)。
实现良好的交叉编译体验
Rust 项目如果依赖 C 通常也能进行交叉编译(依赖 cc
crate),但一旦失败,错误会很难调试。系统库链接也常常引发混乱和难以复现的问题。
而 bzip2 在编译为 WebAssembly 时一直是个麻烦。通过去除 C 依赖、使用 Rust 实现,这类问题就自然消失了:交叉编译"直接就能用"。构建 Windows 或 Android 版本也变得简单。
这不仅提升了用户体验,也极大降低了维护负担。
默认不导出符号
C 依赖的符号会被导出,以便 Rust 的 extern
块能够调用。但如果另一个依赖也声明了相同符号,可能会发生冲突。
libbz2-rs-sys
默认不导出符号,这样就不会与其他库冲突。如果你的 Rust 项目确实需要导出符号,可以通过特性开关(feature flag)启用导出。
使用 MIRI 运行测试
要写出高性能的 bzip2 实现不可避免要用一些 unsafe 代码,复刻 C 接口的部分更是如此。幸运的是,我们能在 MIRI 下运行这些代码。
更重要的是,任何依赖 bzip2 的高层库或应用程序,现在也能在 MIRI 下进行验证。
安全审计
安全审计发现了一个逻辑错误(off-by-one 错误),并修复了一些 fuzzer 的限制。除此之外没有发现重大问题(太棒了!)。
特别感谢来自 Radically Open Security 的 Christian Reitter,他分享了 fuzzing 方面的专业经验。完整审计报告可以在项目页面查看。
结语
现在,bzip2 crate 更快了。你可以继续安心地"忘了它的存在"。
致谢
- 感谢 Alex Crichton 共同维护 bzip2 crate
- 感谢 Radically Open Security 的审计和专业建议
- 感谢 NLnet 基金会资助本次工作