BunがZigからRustへの11日間のAI駆動コード移行を完了

iconMetaEra
共有
AI summary icon概要
Bunは2026年5月にプロジェクトの発表を行い、ZigからRustへの11日間のAI駆動コード移行を完了しました。この作業では100万行以上のコード、6,778回のコミット、64台の並列Claudeインスタンスを用い、コストは165,000ドルでした。2,000回のビルド後、メモリ使用量は6.7GBから609MBに減少し、パフォーマンスは2〜5%向上しました。現在のコードには13,000個のunsafeキーワードと19のレグレッションが含まれています。Anthropicがこのプロジェクトを所有しています。このAI+暗号通貨ニュース更新は、プロジェクトのインフラにおける大きな変化を示しています。
Bunプロジェクトは2026年5月にZigからRustへの大規模なコード移行を完了し、11日間で100万行以上のコード変更と6,778回のコミットを実施しました。この移行には64個のClaudeを並列で使用し、APIコストは16.5万ドルがかかりました。移行後、メモリリークの問題が根本的に解決され、2,000回のビルド後にメモリ使用量が6.7GBから609MBに安定しました。パフォーマンスは2%~5%向上し、バイナリファイルのサイズは約20%削減されました。ただし、コードには約13,000個のunsafeキーワードが存在し、同種のプロジェクトと比較して178倍の量です。また、既知の19のリグレッション問題が存在し、100万行の変更は人間が1行ずつレビューすることは不可能です。現在、BunはAnthropicに買収されています。

記事作成者、出典:InfoQ

2026年5月、Bunプロジェクトは、ソフトウェア開発の歴史において非常に稀な大規模なコード移行を完了した。

この移行は5月3日に開始され、5月14日にメインブランチに正式にマージされるまで、わずか11日で完了しました。コードの作成は6日で済み、プロセス全体は公開されていました。しかし、Jarred Sumnerがブログでまとめを書くのにほぼ1か月かかり、コード作成の時間よりも長くなりました。

このJavaScriptランタイムは、コメントを除いて元々535,496行のZigコードを含んでおり、約20%のコードはC++で記述され、複数のC/C++ライブラリが組み込まれていました。今回のAIを活用したRustへの書き換えでは、100万行以上のコード変更、6,778回のコミットが行われ、Claude Code上で約50のダイナミックワークフローが実行されました。

サマーが開示したデータによると、このリライトはAPIレベルで59億個の非キャッシュ入力トークン、6.9億個の出力トークン、および720億個のキャッシュ入力トークン読み取りを消費し、API料金に基づくと約16.5万ドルの費用がかかりました。

サマーは、これは現在の技術が達成できる最前線であると述べた。彼は、完全にBunのコードベースに精通したエンジニア3人でこの移行を手作業で行うには約1年かかると推定し、その間、チームは新機能の開発、バグ修正、セキュリティ修正をほとんど進められなくなるだろうと述べた。

このリライト後、Bun v1.3.14 が最後の Zig バージョンとなり、Bun v1.4.0 が最初の Rust バージョンになります。

1 成果:メモリリークが6.7GBから609MBの安定状態に改善

Bunは当初、Zigで構築された広範なプロジェクトであり、JavaScriptおよびTypeScriptのトランスパイラ、バンドラー、パッケージマネージャー、テストランナー、モジュール解決ツール、HTTPおよびWebSocketクライアント、さらにNode.js APIレイヤーを実装している。この広範な機能により、BunのCLIは月間2200万回以上のダウンロードを記録し、Vercel、Railway、DigitalOcean、Claude Code、OpenCodeなどのプロジェクトや企業からサポートを受けている。

しかし、同じ幅であることはBunにもいくつかの課題をもたらしました。

Bun v1.3.14 では、長年困扰用户的問題が存在しました:Bun.build() を連続して呼び出すと、メモリが継続的に蓄積され、解放されません。1回のビルドで約3MBのメモリリークが発生し、一見小さな量に見えますが、開発サーバーを実行し、リクエストごとにビルドがトリガーされる場合、メモリは徐々に消費され、プロセスがクラッシュするまで続きます。

実際のテストでは、500回のビルド後にメモリ使用量が1.9GB、1000回後に3.5GB、1500回後に5.1GB、2000回後に6.7GBに急増しました。

これは多くのメモリ問題の氷山の一角にすぎません。v1.3.14のバグ修正リストで、サマーは長く詳細な問題の一覧を挙げました:

zlib モジュールで .reset() を呼び出す際、スレッドプールでまだ非同期の .write() が実行中であると、プロセスは「ヒープ解放後の使用」によりクラッシュする。http2 モジュールでは、ネストされた JavaScript コールバックがハッシュテーブルの再ハッシュをトリガーし、内部ストリームポインタが無効になる。UDPSocket.sendMany() が繰り返し処理中に、ユーザー側のコードが valueOf や toString のコールバックを通じてソケットの接続状態を変更すると、境界外書き込みが発生する。crypto.scrypt は出力バッファの割り当てに失敗した場合、コールバックと保護されたパスワードバッファが永遠に解放されない。......

これらのバグの共通点は明確です——ほぼすべてが、GCと手動メモリ管理を同じソフトウェア内で混在させることに起因しています。

JavaScriptCore(およびV8)のような現代的なエンジンは、例外処理とGCに対して極めて厳格なルールを設けており、ZigはC言語のようにメモリを自動的に管理しません。これらのパラダイムが同じプロセス内で共存する場合、すべてのメモリ割り当てを1行ずつ検証する必要があります:これらのバイトはどこで解放されるのか?解放は1回だけであることをどうやって保証するのか?JavaScriptの例外は正しくチェックされているか?GCが管理するこのポインタは保守的なスタックスキャナに可視か?これはGCメモリなのか、それとも手動で管理されるメモリなのか?

さらに不安なのは、チームが努力していないわけではないことだ。彼らはZigコンパイラにAddress Sanitizer(ASAN)のサポートを追加し、毎回のコミットでCI内でASANテストを実行し、Windows上でReleaseSafeビルドを行い、Fuzzilliを用いて24/7のファジングテストを実施し、多数のエンドツーエンドのメモリリークテストも行っている。にもかかわらず、クラッシュレポートは絶え間なく届き続けている。

「私たちのバグ修正リストはとても気分が悪い。Bunのクラッシュを恐れて眠りにつくのが嫌になった。」とSumnerは書いた。彼はZigを責めていない。他のZigユーザーは、GCと手動メモリ管理を混在させるという極めて稀な要件に直面していないため、Bunのような問題には遭遇していない。このような要件には、ほとんどすべての言語が設計されていない。

一方、Rust版の結果は、2000回のBun.build()を実行してもメモリ使用量が609MBに安定していることです。

メモリリークの問題が根本的に解決されただけでなく、Rustへの書き換えにより他の複数の面でも改善がもたらされました。

安定性面で、v1.4.0 は v1.3.14 で再現可能な 128 個のバグを修正しました。メモリリークからクラッシュ、色の表示エラーを含むヘルプテキストまですべて解決されています。

体積面では、Rustでの書き換え、ICUの変更、および同じコードの折りたたみにより、BunのLinuxおよびWindows上のバイナリサイズは約20%削減されました。

パフォーマンス面で、全体的に2%から5%向上しました。Bun.serveは16.96万req/sから17.77万req/sへ、node:httpは10.38万から10.85万へ向上しました。実際のアプリケーションでは、next buildが13.62秒から13.03秒へ、tscバッチコンパイルが0.94秒から0.89秒へ短縮されました。

Rust BunベースでClaude Codeがリリースされた後、Linuxでの起動時間は517msから464msに短縮され、約10%高速化されました。

2 方法:64のClaude、11日間、50のワークフロー

サマーはどのようにしてそれを実現したのか?これはおそらく最も注目すべき点です——彼が使用した方法は、従来の「AIにコードを書かせる」方法とは異なるからです。

サマーは、このプロセスを約50のダイナミックなワークフローに分割し、それぞれがループとなっています。彼はブログでこのパターンを疑似コードで説明しています:

各タスクにはコンテキスト(例:JiraチケットやGitHubイシュー)があり、Claudeはそのコンテキストに基づいてコードを記述し、その後2人のレビュアー(これもClaude)がコードをレビューし、フィードバックを適用します。完了次第、次のタスクに進みます。

このモードは、全体のリライトプロセスに貫かれています。各ワークフローは特定の目標を担当します:

  • Zigのパターンと型をRustのパターンと型にマッピングするためのポートガイドを作成する;
  • 各 .zig ファイルを機械的に .rs ファイルに移植し、PORTING.md と LIFETIMES.tsv と一致させる;
  • 各crateのコンパイルエラーを修正する;
  • bun test や bun build などのサブコマンドを実行する;
  • Bunのテストスイート内のすべてのテストを通過させ、複数回の大規模なリファクタリングとクリーニングを実施する。

ピーク時には、Sumnerが4つのワークフローを同時に実行し、各ワークフローに16のClaudeが含まれ、合計64のClaudeが4つのワークツリーで並列に動作し、それぞれファイルをコミットしてプッシュしました。最高峰時には、Claudeが1分間に約1300行のコードを書きました。

この「実装者/レビュー者」の分離設計が鍵です。コードを書くClaudeは、人間のエンジニアと同じように、コードが受け入れられたいという偏見を持っています。そのため、レビュー者と実装者は完全に分離されており、レビュー者は実装者の推論プロセスを見ず、明確に「コードは誤っていると仮定する」ように指示されます。各実装者には2人以上の対抗的なレビュー者が割り当てられ、レビュー者の唯一の仕事はバグを見つけることです。

コードの記述は最初のステップにすぎません。Zigのコードは単一のコンパイルユニットですが、Rustはコンパイル速度を向上させるために約100のクレートに分割されます。循環依存により、cargo checkが一度に約16,000個のコンパイルエラーを出力します。これは一人にとって災難ですが、64台のClaudeが並列で作業するには処理可能なワークキューです。ワークフローではエラーをクレートごとにグループ化し、各クレートに対してcargo checkを実行。1つのClaudeが修正し、2つがレビューし、1つが変更を適用します。

次に、bun --version を実行し、その後 bun test を実行します。テストワークフローは、毎回100個のテストファイルをランダムに選択し、4つのワークツリーに分割して実行します。テストスイートには複数の種類が含まれており、一部のテストは1分以上実行され、一部はシステムのTCP接続数を消費し、一部は約10,000個のプロセスをforkします。Sumnerはsystemd-runを使用してcgroupを作成し、リソースを制限しましたが、マシンはディスクスペース不足により複数回クラッシュしました。

2日後、Linuxプラットフォームの失敗テストは972件から23件に減少した。1日半後、Linuxはすべて正常となった。5日後、Linux x64、Linux arm64、macOS x64、macOS arm64、Windows x64、Windows arm64のすべての6つのプラットフォームが合格した。

5月14日、PR #30412が正式にマージされ、テストスイートがすべて通過し、どのテストもスキップまたは削除されませんでした。

3 懸念:13,000件の安全でなく、行ごとにレビューできないコード

しかし、サマーは、この作業がまだ本当に終わっていないことを認めています。

現在までに、BunのRustコードの約4%がunsafeブロック内にあり、約13,000個のunsafeキーワードが約27,000行のコードに分散しており、Rustの総コード量は約780,000行です。そのうち78%のunsafeブロックは1行であり、通常はC++からのポインタまたはCライブラリへの1回の呼び出しです。

今後の再構築により、この比率は低下すると予想されている。しかし、誰かが計算したところによると、uvは約35万行のコードに対してunsafe呼び出しが73回のみであるのに対し、Bunのunsafe呼び出しはuvの178倍である。この差は「Cライブラリを呼び出す必要がある」という理由では説明しづらい。

その後、安全なRustコードでも未定義動作が発生しました。安全なコードは問題が起こらないはずだと信じてしまうため、C++よりもデバッグが困難です。

Bunチームはその後、この問題におけるPathString::initをunsafe fnに変更した。

サマー自身も、このリライトにより19の既知のリグレッション問題が導入されたことを認め、その大多数は構文は同じだが意味が異なるコードに起因していると述べた。

これらのコードスニペットは似ていますが、動作はまったく異なります。Zigのコードではassertは関数であるため、ビルドごとにその引数が実行されます。Rustのコードではdebug_assert!はマクロであり、リリースビルドでは、関数呼び出しを含む全体の式が削除されます。

問題はすべて修正されましたが、これは百万行のAIコードに他の問題がないことを意味しません。

誰が、ランタイムが完全に書き換えられた直後に、自社の本番アプリケーションを移行するだろうか?1.4版には新しいバグが含まれていない、または動作に変更がないと信じるのは、あまりにも甘い考えだ。

見過ごせないもう一つの課題はコードレビューです。100万行の変更を人間が1行ずつ確認するのは現実的ではありません——1分あたり1行を確認したとしても、連続で11.7日かかります。実際のコードレビュー速度(1時間あたり200行)で考えると、2年以上かかってしまいます。

今回のPRのレビュー担当は主にclaude[bot]とcoderabbitai[bot]です。Sumner自身も、自分のレビュー方法は「対抗的なレビューagentが差異を正しく捕捉しているかを確認し、変換ガイドラインが守られているかを確保すると同時に、自らも多数のコードを手動で読みました」と認めています。しかし、「多数」とは具体的にどれくらいかについては言及していません。

まだ避けられない問題があります:Bunは2025年12月にAnthropicに買収され、このコードベースを実質的に維持できるツールは、Claude自身だけです。コミュニティでは、これはもはや伝統的なオープンソースプロジェクトとは言えないという声があります——BunにPRを送るには、Anthropicにサブスクライブするか、AIが生成したコードをすでに理解している数名のコアメンバーに期待するしかありません。

16万5千ドルで1年分の労働を交換するのは、価値があるか?

サマーはブログで、このAPIの書き換えにかかるコストは約16万5,000ドルであり、これは3人のエンジニアが1年間で働く分に相当すると明らかにしました。この数字はHacker News上で激しい議論を呼びました。

一部の人は、この費用は実際には非常にコスパが良いと考えている。シリコンバレーで16万5,000ドルを支払っても、全職のエンジニアを数人雇うのがやっとであり、Anthropicのようなレベルの企業のエンジニアを雇うのはさらに難しい。levels.fyiの給与データによると、Anthropicのエンジニアの総報酬は50万ドルに達する可能性があり、さらにそれ以上になることもある。50人のエンジニアの平均年収を33万6,000ドルと仮定しても、1日あたり約1,292ドルに相当する。50人が11日間連続で働いた場合、人件費だけで約71万ドルに達し、福利厚生、オフィススペース、機器、その他の管理費は含まれていない。

しかし、サマーは一般に公開されておらず、輸出規制の対象となる可能性のある高度なモデルである「Claude Fable 5」のプレリリース版を使用しています。したがって、APIの価格はエンドユーザーが見る数字にすぎず、その背後にはAnthropicが投入した巨額の研究開発費用があります。また、コストをAPI価格に単純化することで、実際の投資を意図的に軽視しているという指摘もあります。モデルの開発コスト、トレーニングコスト、計算リソースの投入、エンジニアリング人材などすべてを含めれば、最終的な総コストは非常に高くなり、おそらく150万ドルを超えるでしょう。

そして現在のところ、16万5000ドルで1年分の労働量を手に入れるのは、帳簿上では非常に得のように見えます。

しかし、本当のコストはこの請求書には含まれていない。このコードベースには6,778回のコミットがあり、誰もがそれを最初から最後まで完全に読み込んだことはない。現在は問題なく動いているが、6か月後はどうなるのか?深夜3時に奇妙な並列問題が突然発生したとき、当直のエンジニアは、自分自身で内部ロジックを説明できないシステムと向き合うことになる。将来的にはAIで保守しなければならず、その保守コストをどう計算するのか、実は非常に難しい。

免責事項: 本ページの情報はサードパーティからのものであり、必ずしもKuCoinの見解や意見を反映しているわけではありません。この内容は一般的な情報提供のみを目的として提供されており、いかなる種類の表明や保証もなく、金融または投資助言として解釈されるものでもありません。KuCoinは誤記や脱落、またはこの情報の使用に起因するいかなる結果に対しても責任を負いません。 デジタル資産への投資にはリスクが伴います。商品のリスクとリスク許容度をご自身の財務状況に基づいて慎重に評価してください。詳しくは利用規約およびリスク開示を参照してください。