Bun 項目於 2026 年 5 月完成從 Zig 到 Rust 的重大程式碼遷移,11 天內完成超過 100 萬行程式碼變更、6778 次提交。遷移過程使用 64 個 Claude 並行工作,消耗 16.5 萬美元 API 成本。遷移後,記憶體洩漏問題得到根本解決,2000 次 build 後記憶體從 6.7 GB 穩定在 609 MB,效能提升 2% 至 5%,二進位檔案體積減少約 20%。但程式碼中存在約 13000 個 unsafe 關鍵字,為同類項目的 178 倍,並存在已知的 19 個回歸問題,且 100 萬行程式碼變更無法由人類逐行審查。目前 Bun 已被 Anthropic 收購。文章作者、來源:InfoQ
在 2026 年 5 月,Bun 項目完成了一次在軟體開發史上近乎罕見的大規模程式碼遷移。
這次遷移從 5 月 3 日啟動,到 5 月 14 日正式合併入主分支,只用了 11 天。寫代碼只用了 6 天,並且整個過程公開。但 Jarred Sumner 寫部落格總結卻花了快一個月,比寫代碼的時間長多了。
這個 JavaScript 運行時原本擁有 535,496 行 Zig 代碼,不包括註釋;同時,約 20% 的代碼由 C++ 編寫,並嵌入了多個 C/C++ 庫。此次借助 AI 重寫為 Rust,整個過程涉及超過 100 萬行代碼變更、6778 次提交,並在 Claude Code 中運行了大約 50 個動態工作流(dynamic workflows)。
根據 Sumner 揭露的數據,這次重寫在 API 層面消耗了 59 億個未快取輸入 token、6.9 億個輸出 token,以及 720 億個快取輸入 token 讀取,按 API 定價計算約花費 16.5 萬美元。
Sumner 表示,這是目前技術所能達到的前沿水平。他估計,如果讓 3 名完全熟悉 Bun 代碼庫的工程師手動完成這次遷移,大約需要一年時間,而且在這一年裡,團隊幾乎無法繼續推進新功能開發、bug 修復和安全修復。
此次重寫後,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() 調用時,記憶體會持續累積且永不釋放。每次建構大約洩漏 3MB,看似不多,但如果你運行的是開發伺服器,每次請求都會觸發一次建構,那麼記憶體就會被一點點吞噬,直到進程崩潰。
在實際測試中,執行 500 次構建後記憶體佔用 1.9GB,1000 次後 3.5GB,1500 次後 5.1GB,2000 次後飆升到 6.7GB。

這只是眾多記憶體問題的冰山一角。在 v1.3.14 的錯誤修復清單中,Sumner 列出了一長串問題:
在 zlib 模組中調用 .reset() 時,若仍有異步的 .write() 正在執行緒池中運行,進程會因「堆釋放後使用」而崩潰;在 http2 模組中,嵌套的 JavaScript 回呼觸發了雜湊表重雜湊,導致內部流指標失效;UDPSocket.sendMany() 在遍歷過程中,若使用者代碼透過 valueOf 或 toString 回呼改變了套接字的連線狀態,就會發生越界寫入;crypto.scrypt 在輸出緩衝區配置失敗時,回呼與受保護的密碼緩衝區將永遠無法釋放;......這些 bug 的共性非常明顯——它們幾乎都指向同一個根源:在同一個軟體中混合使用 GC 與手動記憶體管理。
現代引擎如 JavaScriptCore(以及 V8)對異常處理和 GC 有極其嚴格的規則,而 Zig 像 C 語言一樣不會自動管理記憶體。當這兩種範式在同一個進程中運行時,每個記憶體分配都需要逐行審查:這些位元組在哪裡被釋放?如何確保只釋放一次?是否正確檢查了 JavaScript 異常?這個由 GC 管理的指標對保守堆疊掃描器可見嗎?這是 GC 記憶體還是手動管理的記憶體?
更令人焦慮的是,團隊並非沒有努力。他們已經對 Zig 編譯器進行了修改,增加了 Address Sanitizer 支持(ASAN),每次提交都在 CI 中運行 ASAN 測試,在 Windows 上使用 ReleaseSafe 構建,用 Fuzzilli 進行 24/7 的模糊測試,並進行了大量端到端的記憶體洩漏測試。即便如此,崩潰報告仍源源不斷。
「我們的 bug 修復清單讓人感覺很糟糕,我厭倦了帶著對 Bun 崩潰的擔憂去睡覺。」Sumner 寫道。他並未責怪 Zig——其他 Zig 用戶並未遇到 Bun 這樣的問題,因為將 GC 與手動管理記憶體混合使用,本身就是一種極為罕見的需求,幾乎沒有語言為此設計。
而 Rust 版本的表現為:同樣執行 2000 次 Bun.build(),記憶體穩定在 609MB。
除了內存洩漏問題得到根本性解決,Rust 重寫還帶來了其他幾個維度的改善。
在穩定性方面,v1.4.0 修復了 v1.3.14 中可重現的 128 個 bug,包括記憶體洩漏、崩潰到顏色顯示錯誤的幫助文字。
By volume, combining the Rust rewrite, ICU changes, and identical code folding, Bun has reduced its binary size by approximately 20% on Linux and Windows.

在性能方面,普遍提升了 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 秒。
而 Claude Code 在基於 Rust Bun 發布後,Linux 上的啟動時間從 517ms 降至 464ms,快了約 10%。

2 方法:64 個 Claude,11 天,50 個工作流
Sumner 是怎麼做到的,這可能是最值得關注的部分——因為他使用的方法,與傳統的「讓 AI 寫代碼」不同。
Sumner 將整個過程拆分成大約 50 個動態工作流,每個工作流都是一個迴圈。他在部落格中用偽代碼描述了這個模式:

每個任務都有一個上下文(例如一個 Jira ticket 或 GitHub issue),Claude 基於這個上下文撰寫代碼,然後由兩位審查者(同樣是 Claude)審查代碼,最後應用反饋。完成後,再處理下一個任務。
這種模式貫穿了整個重寫過程。每個工作流負責一個特定目標:
- 生成一份 porting guide,把 Zig 的模式和類型映射到 Rust 的模式和類型;
- 將每個 .zig 檔案機械式移植為一個 .rs 檔案,並對應 PORTING.md 和 LIFETIMES.tsv;
- 修復每個 crate 的編譯錯誤;
- 讓 bun test 或 bun build 這樣的 subcommand 執行;
- 讓 Bun 測試套件中的每個測試都通過;進行數輪大型重構與清理。
在高峰期,Sumner 同時運行了 4 個工作流,每個工作流包含 16 個 Claude,總共 64 個 Claude 同時在 4 個工作樹中並行運作,各自提交和推送檔案。在最高峰時,Claude 每分鐘撰寫了約 1300 行代碼。
這種「實現者/審查者」的分離設計至關重要。撰寫代碼的 Claude 和人類工程師一樣,希望代碼能被接受,因此存在偏見。因此,審查者與實現者完全分開——審查者僅查看代碼差異,不查看實現者的推理過程,並被明確告知「假設代碼是錯的」。每個實現者對應兩個以上的對抗性審查者,審查者的唯一工作就是尋找 bug。

寫完代碼只是第一步。Zig 代碼是單一編譯單元,而 Rust 則需拆分成約 100 個 crate 以加快編譯速度,循環依賴導致 cargo check 一次性輸出約 16000 個編譯錯誤。對一個人來說這是災難,但對 64 個並行工作的 Claude 來說,這只是一個可處理的工作隊列。工作流程將錯誤按 crate 分組,每個 crate 執行一次 cargo check,由一個 Claude 修復,兩個審查,一個應用修改。
接下來是執行 bun --version,然後是 bun test。測試工作流程每次隨機運行 100 個測試文件,並分片到 4 個工作樹。測試套件也包含多種類型:有些測試會運行超過一分鐘,有些會耗盡系統的 TCP 連接數,有些會 fork 約 10000 個進程。Sumner 使用 systemd-run 建立 cgroup 來限制資源,但機器仍因磁碟空間不足而崩潰了好幾次。
兩天後,Linux 平台的失敗測試從 972 個降至 23 個。一天半後,Linux 全綠。五天後,全部六個平台——Linux x64、Linux arm64、macOS x64、macOS arm64、Windows x64、Windows arm64——全部通過。
5 月 14 日,PR #30412 正式合併,測試套件全部通過,沒有跳過或刪除任何測試。

3 隱憂:13,000 個 unsafe 和無法逐行審查的程式碼
不過,Sumner 也承認,這項工作還沒有真正結束。
截至目前,Bun 的 Rust 程式碼中約有 4% 位於 unsafe block 內,約 13,000 個 unsafe 關鍵字,分佈在約 27,000 行程式碼中,而 Rust 總程式碼量約為 780,000 行。其中 78% 的 unsafe block 只有一行,通常是一個來自 C++ 的指標,或一次對 C 函式庫的呼叫。
他預計後續的重構會讓這個比例下降。但有人算了一筆賬:uv 約 35 萬行程式碼,僅有 73 次 unsafe 調用。而 Bun 的 unsafe 數量是 uv 的 178 倍。這個差距很難用「需要調用 C 庫」來解釋。
並且隨後在安全的 Rust 代碼中也暴露了未定義行為。這比 C++ 更難調試,因為你會以為安全代碼不可能出問題。

Bun 團隊隨後將該問題中的 PathString::init 改為 unsafe fn。
Sumner 也承認,這次重寫引入了 19 個已知的回歸問題,並表示大多數回歸問題都源於語法相同但語義不同的代碼。

這兩個程式碼片段看起來很相似,但行為卻截然不同。Zig 的程式碼 assert 是一個函數,因此其參數在每次建構時都會執行。Rust 的程式碼 debug_assert! 是一個巨集,因此在發行版本中,整個表達式(包括函數呼叫)都會被刪除 insert_stale。
雖然所有問題都已修復,但這並不表示百萬行 AI 代碼沒有其他問題。

正常人誰會在一個運行時被徹底重寫之後,立刻把自己的生產應用遷過去?如果以為 1.4 版本沒有引入新的 bug,或者沒有帶來行為變化,那就太天真了。還有一件不能忽略的事情是程式碼審查。100 萬行的變更實際上無法由人類逐行查看——即使每分鐘看一行,也要連續看 11.7 天;按實際的程式碼審查速度(每小時 200 行),則需要兩年多才能看完。
這次 PR 的審查者主要是 claude[bot] 和 coderabbitai[bot]。Sumner 自己也承認,他的審查方式是「檢查對抗性審查 agent 是否正確捕獲了差異,確保轉換指南被遵守,同時自己也手動讀了不少代碼」。但「不少」是多少,他沒說。
還有一個無法迴避的問題:Bun 在 2025 年 12 月 被 Anthropic 收購,真正能有效維護這套程式碼庫的工具,基本上只有 Claude 自己。社區中有人表示,這已算不上傳統意義上的開源項目——你想為 Bun 提交 PR,得先訂閱 Anthropic,或指望那幾個已經看懂 AI 生成代碼的核心成員。
16.5 萬美元換一年工作量,值得嗎?
Sumner 在博客中還披露,這次重寫的 API 成本約為 16.5 萬美元,相當於 3 名工程師一年的工作量。這個數字在 Hacker News 上引發了激烈的討論。
有人認為,這筆賬其實很划算。在矽谷,16.5 萬美元請不到幾名全職工程師,更不用說 Anthropic 這種級別公司的工程師了。根據 levels.fyi 上的薪資數據,Anthropic 工程師的總包很可能達到 50 萬美元甚至更高。即便按 50 名工程師平均年薪 33.6 萬美元粗略計算,折合到每天大約是 1292 美元。50 個人連續工作 11 天,僅人力成本就已接近 71 萬美元,還不包括福利、辦公場地、設備和其他管理開銷。

但 Sumner 使用的是「Claude Fable 5 的預發布版本」,這是一個尚未對公眾開放、可能受出口管制的高階模型。因此,API 定價僅是最終用戶看到的數字,背後是 Anthropic 投入的巨額研發費用。還有觀點指出,將成本簡化為 API 定價,是在刻意淡化真實投入。若計入模型研發成本、訓練成本、算力投入、工程人力等,相信最終總成本必然很高,很可能超過 150 萬美元。

而且目前看來,雖然 16.5 萬美元換一年工作量,賬面上看挺劃算。
但真正的成本並不在這張賬單上。這個代碼庫有 6778 次提交,沒有人從頭到尾完整讀過,雖然眼下一切正常,可六個月後呢?當某個詭異的併發問題在凌晨三點突然冒出來,負責值班的工程師面對的是一個連他自己都說不清內部邏輯的系統。延伸到以後都得 AI 來維護,維護成本怎麼算,其實挺難。

