Bun 1.4: AI を使ってランタイムを Rust に書き直す

Bun 1.4: AI を使ってランタイムを Rust に書き直す

Bun は v1.4.0 リリースに向けてコアランタイムを Rust で書き直し、メモリ安全性の脆弱性を体系的に排除し、安定性を向上させました。Claude Fable 5 のプレリリース版と自動化された「アドバーサリアルレビュー」ワークフローを活用し、チームは 11 日間で 500,000 行以上の Zig コードを Rust に移植し、バイナリサイズを 20% 削減、パフォーマンスを 2〜5% 向上させました。

なぜ Bun は Zig から Rust に移行したのか

Bun は当初、低レベル制御と高性能を活かすために Zig で構築されました。しかし、トランスパイラ、パッケージマネージャ、テストランナー、Node.js API 実装などを含むプロジェクトの規模が大きくなるにつれ、安定性の課題が顕在化しました。

体系的なメモリ安全性問題

書き直しの主な動機は、スタイルガイドや手動レビューだけでは解決が難しい再発するメモリバグのクラスです。Bun v1.3.14 では、チームは以下のような多数の重大問題を特定しました:

  • Use‑after‑free クラッシュnode:zlibnode:http2 で、非同期操作や再入可能な JS コールバックが原因。
  • Double‑free クラッシュ – CSS パーサで発生。
  • メモリリークcrypto.scrypttlsSocket.setSession()fs.watch() で、参照カウントのアンダーフローやクリーンアップ呼び出しの欠如が原因。

チームは Address Sanitizer (ASAN) と 24/7 の Fuzzilli によるファジングを使用していましたが、Zig には自動メモリ管理がないため、すべての割り当てに対して綿密な手動レビューが必要でした。Rust を選んだ理由は、借用チェッカーと Drop トレイトがこれらのメモリ安全性エラーをコンパイラエラーに変換し、手動コードレビューよりも速く信頼性の高いフィードバックループを提供できるからです。

AI 主導の書き直しプロセス

従来のインクリメンタルな書き直しとは異なり、一時的な「接着」コードが生まれやすい手法を取らず、Bun チームはコードベース全体の機械的ポートを実施しました。これは Claude Code と一連の動的ワークフローを用いて実現されました。

「アドバーサリアルレビュー」ワークフロー

LLM が生成したコードの品質を保証するため、チームは分割コンテキストレビューシステムを導入しました:

  1. 実装者: 元の Zig ソースとポーティングガイドに基づき Rust コードを書き出す Claude インスタンス。
  2. アドバーサリアルレビュアー: 差分のみを受け取る 2 つの別個の Claude インスタンス。彼らの唯一の目的はバグを見つけ、コードが間違っていることを証明することです。
  3. フィクサー: レビュアーからのフィードバックを適用する最終インスタンス。

このプロセスにより、js_bun_spawn_bindings.rs における非同期 uv_close の性質によって引き起こされた use‑after‑free/double‑free バグなど、標準的なコンパイラチェックでは見逃される重大バグが捕捉されました。

実行と規模

  • 期間: 11 日間(5 月 3 日〜5 月 14 日)。
  • ボリューム: 6,502 コミット、ピーク時は 1 分間に 1,300 行のコードを生成。
  • インフラ: 4 つのワークツリーにまたがって 64 個の同時 Claude インスタンスを稼働。
  • コスト: API トークンで約 $165,000。

Bun v1.4.0 の技術的改善点

メモリ使用量と安定性

Rust の Drop トレイトへの移行により、いくつかの計測可能なメモリリークが解消されました。例として Bun.build() では、v1.3.14 でビルド数が増えるにつれてメモリ使用量が線形に増加し(2,000 ビルドで 6.7 GB に達した)ましたが、v1.4.0 では約 609 MB で頭打ちになります。

バイナリサイズとパフォーマンス

  • バイナリサイズ: Linux と Windows で約 20% 縮小(例: Windows バイナリは 94 MB から 76 MB に)。これは comptime の使用削減と Identical Code Folding などのリンカ最適化によるものです。
  • スループット: HTTP スループットが 2.8%〜4.8% 向上(Bun.serve、Elysia、Fastify などのフレームワーク)。
  • CLI 速度: next buildtsc -b といったアプリワークロードで 2.2%〜4.7% の性能向上。
  • スタック領域: 再帰下降パーサ(JSON、TOML など)が LLVM の llvm.lifetime.startllvm.lifetime.end インストリンスによりスタック使用量を削減。

ポーティング時の課題とリグレッション

自動化プロセスにもかかわらず、書き直しにより 19 件の既知リグレッションが発生しました。多くは Zig と Rust のセマンティクス差に起因します:

  • マクロ除去: Rust の debug_assert! がリリースビルドで副作用呼び出し(insert_stale)を除去するバグが発生。一方 Zig の assert は常に実行される関数です。この問題により特定の React プロジェクトで HMR が壊れました。
  • スライス処理: Rust の bytemuck::cast_slice は奇数長スライスでパニックしますが、元の Zig コードは余剰バイトを無視していました。その結果、特定の UTF‑16 ケースで Blob.text() がパニックしました。
  • 境界チェック: Rust のリリースビルドは境界チェックを保持しており、Zig の ReleaseFast モードで隠れていたモジュールリゾルバのオフバイワンエラーが露呈しました。

コミュニティと業界の視点

Hacker News の議論からは、ソフトウェアエンジニアリングのパラダイムシフトが浮き彫りになっています:

"包括的なテストハーネスを設計・実装することが本当の仕事であり、それができたら LLM に任せればいい。"

批評家は、トークンコスト($165k)が人間チームに比べて労働コスト削減分を相殺する可能性があると指摘する一方、成功の鍵は Bun が既に持っている言語非依存の TypeScript テストスイートにあり、AI が効果的に反復できる「検証可能な報酬」を提供した点にあると評価しています。

Sources