Bun 用 Rust 重写:11 天、96 万行代码和一场 AI 编程的成本争议

AIRustBun

2026 年 5 月 14 日,Bun 运行时的全部 Zig 代码库被合并到了 main 分支。完成这次迁移的是一个人加上 64 个并行运行的 Claude 代理。11 天,约 96 万行代码从 Zig 转写为 Rust,API 成本约 16.5 万美元。

两个月后,社区开始仔细审视这场迁移的账单。

Bun in Rust 官方封面图

背景:从 Zig 到 Rust 的决策

Bun 最初用 Zig 语言编写,于 2023 年发布,是 Node.js 和 Deno 之外的第三个 JavaScript 运行时选项。2025 年 12 月 3 日,Anthropic 宣布收购 Bun,理由是 Bun 已成为 Claude Code 的重要基础设施。

收购之后,语言切换的决策很快浮现。Zig 核心团队有明确的「不接受 AI 贡献」政策,这与 Anthropic 使用 AI 代理进行大规模开发的工作方式产生了冲突。Jarred Sumner 在博客中披露,他使用了 Claude Fable 5 的预发布版本完成大部分 Rust 转写工作。

选择 Rust 的技术理由包括:所有权系统(Ownership)提供的内存安全保证、Drop trait 的确定性资源释放(Zig 没有等价机制)、以及类型系统在编译期能捕获更多错误。Bun 团队此前尝试用 Zig 实现确定性资源释放,但因缺乏类似 Drop 的机制而未能合并。

迁移过程:编译器即工作队列

整个迁移分为两个阶段。Phase A 将 Zig 代码逐文件转写为 Rust,不要求编译通过,只要求逻辑等价。一个名为 PORTING.md 的文档定义了约 300 条 Zig 到 Rust 的转写规则。Phase B 逐 crate 修复编译错误。

Bun 的 Zig 代码库是一个编译单元(等价于一个 crate)。Sumner 将 Rust 版本拆分为约 100 个 crate 以加快编译速度,但这引入了循环依赖问题。在解决循环依赖后,cargo check 报出了约 16,000 个编译错误。

这 16,000 个错误被按 crate 分组,分配给 64 个并行 Claude 代理处理。每个代理修复分配到的错误,提交 PR,经审查后合并。Rust 编译器的错误信息精确描述了所有权和类型失败的原因,这使编译器成为了代理的工作队列和反馈源。

整个迁移消耗了 59 亿个非缓存输入 token 和 6.9 亿个输出 token,另外读取了 720 亿个缓存输入 token。6,755 个 commit 在 5 月 3 日至 14 日之间被合并到 main 分支。

性能数据:改了什么

根据 Bun 官方博客公布的数据,Rust 版本在多个维度上有量化提升:

HTTP 吞吐量(req/s,三轮平均值):

服务v1.3.14 (Zig)v1.4.0 (Rust)变化
Bun.serve169.6k177.7k+4.8%
node:http103.8k108.5k+4.5%
Elysia158.9k163.3k+2.8%
Express64.5k66.6k+3.2%
Fastify91.5k95.9k+4.8%

构建工具(hyperfine 基准测试):

工作负载v1.3.14 (Zig)v1.4.0 (Rust)变化
next build13.62s13.03s+4.5%
vite build1.69s1.65s+2.2%
tsc -b --force0.94s0.89s+4.7%

二进制体积:

平台v1.3.14v1.4.0 (canary)缩减
Windows94 MB76 MB-19%
Linux88 MB70 MB-20%

内存使用(并行构建场景):

构建数v1.3.14v1.4.0缩减
5001,914 MB526 MB-73%
1,0003,506 MB586 MB-83%
1,5005,097 MB608 MB-88%
2,0006,745 MB609 MB-91%

内存使用的改善尤其显著。Zig 版本在并行构建时内存随规模线性增长,Rust 版本的内存使用在 500 构建后基本持平(526→609 MB),因为所有递归下降解析器(TOML、JSON、YAML、JavaScript、TypeScript)现在共享更高效的栈空间管理。

生产验证

Prisma 在 Rust 重写版上启动了 Prisma Compute 公共测试版。Prisma 工程师 Alexey Orlenko 报告,团队此前在 Zig 版本上遇到了内存泄漏和连接池在 VM 暂停恢复后无法自恢复的问题,Rust 版本在相同故障模式下表现正常。

Claude Code v2.1.181(6 月 17 日发布)及后续版本已在生产中使用 Rust 版 Bun。启动时间在 Linux 上快了 10%,Sumner 表示除此之外用户几乎察觉不到变化。

安全争议:13,000 个 unsafe 块

迁移中最受关注的争议是 Rust 代码中的 unsafe 块数量。据 Simon Willison 追踪的 commit 数据,代码库中约有 13,000 到 14,000 个 unsafe 块,而同等规模的手写 Rust 项目通常只有约 73 个。

unsafe 块是 Rust 中绕过编译器安全检查的机制,用于需要直接操作内存的场景(如与 C 库交互或操作裸指针)。每个 unsafe 块的安全性由开发者手动保证。约 13,000 个 unsafe 块意味着大量代码不受 Rust 安全系统保护。

Zig 创建者 Andrew Kelley 将这次迁移的输出称为「未经审查的产物」(unreviewed slop)。Hacker News 上的讨论帖积累了近 800 条评论,开发者社区对此意见分化:一方认为 Rust 编译器在迁移过程中捕获了大量潜在 bug,是类型安全的胜利;另一方认为 13,000 个 unsafe 块在没有充分人工审查的情况下进入生产运行时,构成了实质性的安全风险。

真实成本:被低估的账单

Tom Lockwood 在 7 月 27 日发布的分析文章中提出了对成本叙事的质疑。他的主要发现:

尚未发布正式版本。 截至 7 月 27 日,距迁移合并已过 6 周,Bun 仍无正式 release tag。上一个正式版本(v1.3.14)发布于 5 月 12 日,距此时已 11 周。Bun 历史上最长的发布间隔是 2022 年 10 月到 12 月之间的 6 周。

PR 积压在增长。 7 月 9 日,来自 robobun(Claude Code 代理的标识)的未合并 PR 有 1,277 个。到 7 月 27 日,这个数字增长到 2,475 个。如果每个 PR 的 Buildkite CI/CD 检查需要约 40 分钟,合并所有积压 PR 需要持续运行管道约 86 天。

CI/CD 成本未被计入。 16.5 万美元的 API 成本不含 Buildkite 集群的持续运行费用。Lockwood 估算,如果迁移按每天 1 万美元的速率持续,总支出正在接近 80 万美元。

Lockwood 指出,Bun 团队从未声称迁移已「完成」或仅花费 16.5 万美元。但社区中流传的「AI 在 11 天内完成百万行重写」的说法,省略了仍在持续的成本和未完成的工作。Anthropic 员工仍在直接参与 Rust 代码的维护,robobun 的活动频率在合并后不减反增。

方法论讨论:这次迁移的可复制性

Bun 的迁移成功依赖几个难以复制的条件:

领域专家驱动。 Jarred Sumner 此前已经实现过一次 JavaScript 运行时(Bun 本身就是 Node.js 的重新实现),对每个模块的正确行为有精确预期。AI 代理收到的指令来自一个对该代码库有深度理解的开发者。

已有测试套件。 Bun 在迁移前已有一套覆盖各平台的测试套件。99.8% 的测试在迁移后直接通过,剩余 0.2% 需要修复。测试套件充当了迁移结果的验证基准。

编译器反馈循环。 Rust 编译器的错误信息结构化程度高,能精确描述所有权冲突和类型不匹配的原因。这使得编译错误可以被直接转化为代理的工作项。

Anthropic 的资源支持。 迁移使用的 Claude Fable 5 在迁移时尚未公开发布。每天 1.5 万美元的 API 支出,加上 Buildkite 集群和 Anthropic 员工的直接参与,表明这不是一个典型的开源维护者可以复制的流程。

一个没有这些条件的团队试图用 AI 代理进行百万行级别的语言迁移,可能会面临完全不同的成本结构和质量风险。Bun 的案例更多是一个特定条件下的实验,而非可推广的工程实践模板。

对开发者的实际影响

如果你是 Bun 用户,迁移的影响很小。Rust 版本(v1.4.0 canary)在性能上有小幅提升,二进制体积明显缩小,内存使用在并行场景下大幅改善。API 完全兼容,现有代码不需要修改。

如果你在评估 AI 辅助的大规模代码迁移,Bun 案例提供了一个有数据支撑的参考点:百万行级迁移在特定条件下可行,但成本、质量审查和持续维护的真实投入远超最初的 API 账单数字。