bzip2 crate 从 C 切换为 100% Rust 实现

本文来自 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 基金会资助本次工作
相关推荐
rgeshfgreh2 分钟前
Spring事务传播机制深度解析
java·前端·数据库
Hilaku40 分钟前
我用 Gemini 3 Pro 手搓了一个并发邮件群发神器(附源码)
前端·javascript·github
IT_陈寒40 分钟前
Java性能调优实战:5个被低估却提升30%效率的JVM参数
前端·人工智能·后端
快手技术42 分钟前
AAAI 2026|全面发力!快手斩获 3 篇 Oral,12 篇论文入选!
前端·后端·算法
颜酱43 分钟前
前端算法必备:滑动窗口从入门到很熟练(最长/最短/计数三大类型)
前端·后端·算法
全栈前端老曹1 小时前
【包管理】npm init 项目名后底层发生了什么的完整逻辑
前端·javascript·npm·node.js·json·包管理·底层原理
HHHHHY1 小时前
mathjs简单实现一个数学计算公式及校验组件
前端·javascript·vue.js
boooooooom1 小时前
Vue3 provide/inject 跨层级通信:最佳实践与避坑指南
前端·vue.js
一颗烂土豆1 小时前
Vue 3 + Three.js 打造轻量级 3D 图表库 —— chart3
前端·vue.js·数据可视化
青莲8431 小时前
Android 动画机制完整详解
android·前端·面试