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 基金会资助本次工作
相关推荐
一斤代码2 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子2 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年2 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子3 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina3 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路4 小时前
React--Fiber 架构
前端·react.js·架构
伍哥的传说4 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
qq_424409194 小时前
uniapp的app项目,某个页面长时间无操作,返回首页
前端·vue.js·uni-app
我在北京coding4 小时前
element el-table渲染二维对象数组
前端·javascript·vue.js
布兰妮甜4 小时前
Vue+ElementUI聊天室开发指南
前端·javascript·vue.js·elementui