发生了什么
Bun 作者 Jarred Sumner(Bun 于 2025 年 12 月被 Anthropic 收购,Jarred 现为 Anthropic 员工)用预发布版 Claude Fable 5 + Claude Code 的 Dynamic Workflows,在 11 天内把 Bun 从 Zig 重写为 Rust——535,496 行代码、1,448 个 .zig 文件、6,778 个 commit。
关键数据:
| 指标 | 数值 |
|---|---|
| 耗时 | 11 天(5 月 3 日 → 5 月 14 日合并) |
| 峰值并行 Claude 数 | 64 个(4 个 workflow × 16 个 Claude) |
| 峰值代码产出速度 | 每分钟约 1,300 行 |
| Token 消耗 | 59 亿 uncached input + 6.9 亿 output + 720 亿 cached input |
| API 等价成本 | 约 $165,000 |
| 测试套件断言数 | 超过 100 万(Linux 138 万 / macOS 126 万 / Windows 101 万) |
| 跳过/删除的测试 | 0 |
Claude Code v2.1.181(6 月 17 日发布)起已在使用 Rust 版 Bun,Linux 启动速度提升 10%,几乎没人注意到——Jarred 说"boring is good"。
为什么值得做:Zig 的内存安全问题
Bun 的 bug 列表几乎全是内存安全问题:use-after-free、double-free、error path 里忘记释放、GC 值与手动管理值的生命周期混乱。Zig 没有构造/析构函数,所有清理靠 defer 手动写在每个调用点——忘记写就是内存泄漏,写错位置就是 double-free。
Rust 的 Drop trait 在值离开作用域时自动调用清理代码,这类问题在 safe Rust 里是编译错误。Jarred 的判断:编译器错误是比代码风格指南更好的反馈回路。
传统智慧是"永远不要重写"(Joel Spolsky 2000 年的名言)。但 Jarred 指出:直到最近,编程语言选择对 Bun 这样的项目是一次性决策。编程 Agent 改变了这个等式。
方法论:这不止是"让 Claude 重写"
Jarred 明确说:他不是简单地 prompt "Rewrite Bun in Rust. Don't make any mistakes." 然后祈祷。整个工程是一套精心设计的循环。
核心模式:loops that write & review code
// 伪代码
let task;
while ((task = todoList.pop())) {
const result = task();
const feedback = await Promise.all([review(result), review(result)]);
await apply(feedback, result);
}
大约 50 个 Dynamic Workflow 串联运行,每个 workflow 是一个循环:实现 → 对抗审查 → 修复。
对抗审查(Adversarial Review)
1 个实现者 + 2 个以上对抗审查者。实现者不审查,审查者不实现。
为什么?因为写代码的那个 Claude 想让代码被接受(有动机偏差),而审查的那个 Claude 的唯一任务是找 bug。和人类 code review 一样的分工逻辑。
Jarred 的规则:如果你需要一段长注释来解释为什么这个 workaround 是 OK 的,那代码就是错的——去修代码。
工作流拆解
| 阶段 | 做什么 |
|---|---|
| 准备 | 3 小时和 Claude 讨论 Zig → Rust 的模式映射,产出 PORTING.md(上了 HN 首页)和 LIFETIMES.tsv(每个 struct field 的生命周期标注) |
| 试运行 | 先翻译 3 个文件,1 实现 + 2 审查 + 1 修复,验证流程 |
| 全量翻译 | 1,448 个 .zig → .rs,4 个 worktree 分片并行 |
| 编译修复 | 编译器错误当作工作队列,按 crate 循环修复(出现约 16,000 个编译错误) |
| 冒烟测试 | 逐 CLI 子命令修复 panic 和 linker 错误 |
| 本地测试 | 按测试文件分片循环,每个失败测试 1 实现 + 2 审查 + 1 修复 |
| CI 测试 | CI 失败列表从 972 个测试文件降到 23 个,再到全绿 |
踩过的坑
- Claude 互相踩踏:多个 Claude 在同一个 repo 里跑
git stash/git reset HEAD --hard互相覆盖。解法:禁止 Claude 运行任何不 commit 具体文件的 git 命令。 - 磁盘 IOPS 瓶颈:一个慢
grep就能冻结所有磁盘读写几分钟。忘了调高 EC2 的 IOPS。 - 测试隔离:压力测试会耗尽 TCP socket、写几 GB 到磁盘、spawn 上万个进程。用
systemd-run(cgroups)限制内存/CPU 和隔离 pid namespace。 - Claude 走捷径:把"让所有 crate 编译通过"理解成"把编译报错的函数 stub 掉"。加规则禁止后停止。
跨语言迁移的语义陷阱
重写引入了 19 个已知 regression,大多来自"语法相同但语义不同"的代码。对做迁移的人有参考价值:
| 陷阱 | 说明 |
|---|---|
debug_assert! 吞掉副作用 |
Zig 的 assert 是函数,参数每次都执行;Rust 的 debug_assert! 是宏,release 构建里整个表达式被擦除——包括里面的 insert_stale() 调用,导致 HMR 坏掉 |
comptime 格式字符串 |
Zig 的 comptime fmt 在参数替换前就处理了颜色标记;Rust 函数没有 comptime 参数,颜色标记被错误地应用到参数上 |
| 边界检查差异 | Zig ReleaseFast 去掉边界检查,Rust release 保留——一个 off-by-one 在 Zig 里静默越界,在 Rust 里 panic |
结果:Bun 更好了
- 修了 128 个在 v1.3.14 中可复现的 bug
- 修了所有可检测的内存泄漏:2,000 次
Bun.build()从 6,745 MB 稳定到 609 MB - 二进制体积缩小约 20%:Linux 88→70 MB,Windows 94→76 MB
- HTTP 吞吐提升 2.8%-4.8%,跨语言 LTO 实现了 C/C++ 与 Rust 之间的内联
unsafe代码目前占 4%(约 13,000 个unsafe关键字),78% 的 unsafe block 只有 1 行(调 C 库)
对读者的判断与行动建议
| 你的情况 | 这篇文章给你的信号 |
|---|---|
| 想用 Agent 做大规模重写 | 不是 prompt 一下就完了。核心是测试套件(语言无关 = 可复用)、对抗审查循环、编译器错误当工作队列 |
| 在评估 Agent 能否做"不可能的事" | 百万行重写在 11 天内完成且有测试保障,但前提是 $165K API 成本 + 预发布模型 + 完整测试套件 + 一人全程监控 |
| 做 Agent harness 开发 | 注意"修复生成代码的流程,而不是手工修复代码"这个原则。Jarred 发现问题时是去改 workflow 的 prompt,不是改产出代码 |
| 关注认知负债 | 即使百万行代码由 Agent 写,Jarred 仍然逐行 side-by-side 审查 Zig vs Rust。参见 Vibe Coding 和 Agentic Engineering 的边界 |
一句话结论:这不是"AI 替代了工程师"。这是"一个有完整代码库理解的工程师,用 64 个并行 Agent + 测试套件 + 对抗审查,把自己一年工作量压缩到 11 天"。测试套件是安全网,对抗审查是质量门,人的判断力是不可省略的编排层。