世界を動かす技術を、日本語で。

Bzip2クレートがCから100% Rustに移行

概要

bzip2の最新版0.6.0がリリースされ、 Rust実装 のlibbz2-rs-sysがデフォルトに この変更により 高速化クロスコンパイル容易化 を実現 libbz2-rs-sysは Cダイナミックライブラリ としても利用可能 多くのプロジェクトが依然としてbzip2への依存を持つ現状 パフォーマンスや保守性、セキュリティ面での改善が主な利点

bzip2 0.6.0リリースとRust実装の導入

  • bzip2バージョン0.6.0 の公開
  • デフォルトで Rust実装(libbz2-rs-sys) を採用
  • bzip2 crateが 従来より高速化、クロスコンパイルも容易
  • libbz2-rs-sysは Cプロジェクト向けダイナミックライブラリ としてもビルド可能
  • 90年代のアルゴリズムだが、 多くのプロトコルやライブラリが依然bzip2を必要
  • 深い依存関係の中でbzip2が必要なプロジェクト多数

Rust化の背景と意義

  • zlib-rsの経験 を活かしbzip2実装を近代化
  • C依存から Rust依存へ移行 し、保守・ビルドの負担軽減
  • 以前の実装詳細は 「Translating bzip2 with c2rust」 で解説済み

パフォーマンス向上

  • Rust実装はC実装より全般的に高速
    • 圧縮は特に顕著な高速化
    • レベル設定はメモリ使用量のみ影響し、パフォーマンス差は小
  • ベンチマーク例(CPUサイクル数、低い方が高速)
    • sample3.ref (level 1): C: 38.51M → Rust: 33.53M(-14.87%)
    • silesia-small.tar (level 1): C: 3.43G → Rust: 3.00G(-14.30%)
    • silesia-small.tar (level 9): C: 3.47G → Rust: 3.17G(-9.66%)
  • 展開処理も全体的に 高速化
    • sample3.bz2: C: 2.53M → Rust: 2.42M(-4.48%)
    • zip64support.tar.bz2: C: 2.32G → Rust: 2.11G(-10.00%)
  • macOS上では展開速度にばらつき が見られることも
  • パフォーマンス測定の自動化が難しい環境も存在

クロスコンパイルの容易化

  • RustプロジェクトのC依存解消 でクロスコンパイルが容易
  • C依存時のビルドエラーやシステムライブラリの競合問題を回避
  • WebAssembly・Windows・Android 向けビルドも簡単
  • 保守性向上 とユーザー体験の改善

シンボル競合の防止

  • C依存の場合は シンボルがエクスポートされ競合リスク
  • libbz2-rs-sysは デフォルトでシンボル非エクスポート
  • 必要なら feature flagでエクスポート可能

MIRIによるテスト実行

  • 安全で高性能なbzip2実装にはunsafeコードが必要
  • MIRI でのテスト実行が可能
  • bzip2を利用する上位ライブラリやアプリも MIRIで検証可能

セキュリティ監査と改善

  • Radically Open Security による監査実施
  • オフバイワンのバグ とファザーの制限を修正
  • 重大な問題は他に発見されず
  • Christian Reitter らによるフィードバック
  • 監査レポートの公開

結論と謝辞

  • bzip2 crateは以前より高速化
  • 利用者は意識せずに恩恵を受けられる
  • Alex Crichton へのメンテナンス協力感謝
  • Radically Open Security への監査と専門知識の提供感謝
  • NLnet Foundation による資金提供感謝

Hackerたちの意見

Trifecta Techの実装が、2019年以降アップストリームリリースのないLinuxディストリビューションで使われている「公式」実装を置き換えるのはどれくらい現実的なんだろう?Fedoraは最近、元のAdler zlib実装をzlib-ngに切り替えたから、そういうことは不可能じゃないよね。元のものと互換性のあるC ABIを提供すればいいだけなんだ。

互換性のあるC ABIは提供してるよ。誰かが「ただ」その作業をやれば実現するんだ。

元のものと互換性のあるC ABIを提供すればいいだけなんだ。これって動的リンクとどう関わるの?今のRustツールチェーンって静的リンクを強制してるんじゃないの?

UbuntuはRustのsudoを使ってるから、確かに可能だよ。

それがuutilsの目標だと思う。 https://uutils.github.io/

パフォーマンス向上 uutilsの騒動の後、独立した検証なしで「Rustで書き直した」っていうプロモーションベンチマークを信じる人っているの?

もちろん、これらの結果は自分のシナリオで確認すべきだよ。でも、パフォーマンスにこだわっている人がbzip2を考慮するとはちょっと疑わしいな。設計スペースのどこを見ても、bzip2がzstdに勝るポイントはないし。zstdなら、一般的な入力に対して1/20の時間でより小さな出力が得られるし、同じ時間をかけてもかなり小さい出力が得られる。さらに、zstdの解凍は状況によって20~50倍速いから、bzip2の実装の速度について議論する価値はあまりないように思う。

uutilsの騒動の後 どの騒動のこと?

この「XをRustで書き直す」っていうのは、自分の家を燃やしてから再建して違う色に塗るみたいな感じがする。CPUサイクルを成果として数えるのは、現代のCPUリソースの50%がUIの見た目に使われてる世界では無関係に思える。

節約したサイクルはバッテリーの持ちを延ばすことにつながる。ポーティングの一度きりのコストを誰かが払ったから、今後ずっとより良いパフォーマンスを楽しめるんだ。

個人的には「クロスコンパイルを可能にする」って部分の方がずっと重要で、これは勝利だと思う。同じように、エクスポートされたシンボルやwasmに簡単にコンパイルできることも大事だよね。

バイナリファイルフォーマットのパース(と構築)は、バッファオーバーフローに対してあまり脆弱でない言語を使うのに良い場所だと思う。特に、一般的なフォーマットで、そのコードがいろんなセキュリティコンテキストで使われる可能性があるならなおさら。

CPUサイクルを数えてる それが数え方について嘘をついてないと仮定してね: https://desuarchive.org/g/thread/104831348/#q104831479

「CPUサイクルを成果として数えるのは、現代のCPUリソースの50%がUIの見た目に使われている世界では関係ない気がする。」そんな考え方が、現代のCPUリソースの50%をUIの見た目に使わせるんだよね。

そのサイクルは、いくつかの場所で直接的にお金の節約につながるよ。主にUIが全くないような場所でね。

「CPUサイクルを成果として数えるのは、現代のCPUリソースの50%がUIの見た目に使われている世界では関係ない気がする。」この考え方が、Electronアプリがネイティブアプリに取って代わる原因だし、ほんと嫌だ。こんな風に無駄にするために、より良いCPUやRAMを買うつもりはないよ。

X11とWaylandの関係に似てるね。今のグラフィック開発者たちは若い人が多くて、Xサーバーのボーマーが書いたCコードを維持したくないんだ。リスクが高くて時間もかかるから。Waylandの目標の一つはXを完全に廃止して、もっと長期的にメンテナンスしやすいものに置き換えることなんだ。実際、今のシステムレベルの開発者たちも、ボーマーが書いたGNUコードやCコードを維持したくない理由は似てる。Cは本質的に問題があって、経験豊富な開発者でもその罠を避けるのが難しいからね。だから、Rustの明言されていないけど重要な目標は、すべての重要なCコードを廃止してRustコードに置き換えることなんだ。Ubuntuもこれに賛同してるよ。

あなたはただのエンドユーザーだから、スイートを維持する必要はないよ。OSSではボランティアの時間は貴重な天からの恵みで、ユニコーンの涙の味がするからね。だから、手間を減らして自動化を導入する方法は金のように貴重なんだ。Rustの厳格なコンパイラと適切なテストスイートは、Cを超えるレベルの正確さを保証してくれるよ。プルリクエストをレビューする時に、すべてが期待通りに動いているかを確認する負担が少なくなるから、ウィンウィンな状況だね。

まるで「アカラベス」を現代の観 audience に合わせてアレンジするみたいだね。自分の力を与える物語を語るために。

誰か、これがデフォルトで11件の未解決CVEを解決するか知ってる?皮肉なことに、bzip2クレートには1件のCVEが報告されてるよ。[1] https://app.opencve.io/cve/?product=bzip2&vendor=bzip2_proje...

0.4.4以前のbzip2クレート 今日0.6.0をリリースするみたいだね :>

そのクレートで報告された「おっと、大きなファイルがランタイムエラーを引き起こす」と「おっと、境界ミスがある」というCの間には明らかに対照があるね。誰かがその境界ミスを利用してコード実行を試みるためにどれだけ努力したのか気になるな。それが実現可能かどうかは分からないけど。

このクレートを使って、何百TBものCommon Crawlデータを処理してるから、スピードアップには感謝してるよ。

ここに来たのは、圧縮速度が14%もアップするのは結構いいと思ったから!

ここでbz2を使う理由って何?zstdに一度変換した方が速くない?高圧縮レベルではbzip2よりも全ての指標で優れてると思うけど。

このデータはトレントで入手できるの?

CをRustにトランスパイルするのに何かLLM使ってるの?

精度が必要で、監査が難しいタスク?まさにそこでLLMを使うべきだね /s

トランスパイルするツールを使うなら、幻覚を見ないやつを選んでね。正確であることが大事だから。https://github.com/immunant/c2rust は結構うまくいくって聞いたよ。数年前にQuake3をRustにトランスパイルしたブログ記事もあるよ: https://immunant.com/blog/2020/01/quake3/。生成されたRustはあんまり綺麗じゃないけど、そこからクリーンアップしてもっと「Rustっぽく」することができるよ。

CとRustのバージョンで同じLLVMコード生成(同じ最適化)を使ってるのか気になるな。もしそうなら、スピードアップはどこから来てるんだろう?(例えば、Rustの自動SIMDみたいなやつ?それとも他の部分を手動で最適化したのか、新しい最適化ライブラリを使ってるのか、他に何かあるのかな?)

ちょっと推測してみるけど、Rustはコードジェネレーターにもっとヒントを渡せるんだよね。例えば、Cのポインタほどエイリアシングを気にしなくていいし。詳しくはここを見てみて:https://ja.wikipedia.org/wiki/Aliasing_(computing)#Conflicts...

X、Y、Z言語でのリライトは、スピードアップのチャンスを与えてくれるけど、Rustに特有の何かはないよ。

Cは正直、現代の高性能コードを書くにはあまり良い言語じゃないよね。C99からC21までの約20年間、言語自体が新しい命令にうまく対応するための機能を追加しなかったから、インラインアセンブリなしで書くのが難しかった。clzやpopcnt、clmul、pdepなどの良い抽象マシン命令があると、こういうコードを書くのがかなり楽になるんだよね。

彼らやProssimoが、BGPやOSPF、RIPなどのコアインターネットプロトコルを同じように見直して再実装してくれることを願ってるよ。他のルーティング実装やDNSサーバーもね。