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 基金会资助本次工作
相关推荐
慧一居士21 分钟前
flex 布局完整功能介绍和示例演示
前端
DoraBigHead23 分钟前
小哆啦解题记——两数失踪事件
前端·算法·面试
一斤代码6 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子6 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年6 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子6 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina6 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路7 小时前
React--Fiber 架构
前端·react.js·架构
伍哥的传说8 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
qq_424409198 小时前
uniapp的app项目,某个页面长时间无操作,返回首页
前端·vue.js·uni-app