Rust重写Bun:64 Claude 并行 100 万行代码 你可能已经看到了——Bun 创始人 Jarred Sumner 用 64 个并行 Claude 实例11 天把 53 万行 Zig 代码重写成了 100 万行 Rust。这件事在社区里炸了锅但多数讨论停留在「AI 真牛」的表面结论上。真正值得拆解的不是「能不能」而是「怎么做到的」。一、为什么 Bun 要从 Zig 迁移到 RustBun 的 bug 修复列表读起来像一堂「内存安全警示课」。v1.3.14 修复的这批 bug几乎全是 use-after-free、双重释放、错误路径忘记释放node:zlib在异步.write()未完成时调用.reset()→ 堆释放后使用node:http2的 JS 回调触发哈希表重哈希→内部流指针失效 → use-after-freeUDPSocket.send()的valueOf()回调在载荷捕获与实际发送之间分离了 ArrayBuffercrypto.scrypt的输出缓存分配失败时回调和密码/盐缓存永不释放tlsSocket.setSession()每次调用泄漏一个 SSL_SESSION~6.5KB/次Jarred 的原话很直接「我每天带着崩溃报告睡不着觉。」Bun 的问题在于混合内存管理——JavaScriptCore 的垃圾回收内存与 Zig 的手动管理内存共存这种场景几乎没有语言是专门设计的。Zig 没有构造/析构函数清理代码靠defer在每个调用点手写出错的概率完全取决于开发者的细心程度。二、为什么不选 CBun 已经有约 20% 的代码是 CJavaScriptCore、uWebSockets、BoringSSL 都是嵌入的 C/C 库。往 C 迁移是最自然的选择——能拿到构造/析构函数能删掉大量extern C胶水代码。但 Jarred 的判断很明确C 治标不治本。ASAN、模糊测试、风格指南这些「事后发现」的手段都不能从源头杜绝内存问题。TigerBeetle 的 TigerStyle 和 Google 的 3.1 万字 C 风格指南都是先例——风格指南的执行力永远靠不住。代码审查是「最好努力」编译器报错才是「必然执行」。Rust 的核心逻辑朴素到让人无法反驳清单里那一长串 bug在安全 Rust 里直接是编译错误。三、关键决策一次性全量 vs 增量迁移这是全文信息量最大的决策点。Jarred 根据早年把 esbuild 转译器从 Go 手动移植到 Zig 的经验判断一次性全量迁移更优。增量迁移会遗留大量「过渡代码」短期和中期都会很痛苦。第二个决策是怎么保证质量先做一次忠实的机械翻译让新代码在结构上尽量贴近原 Zig 代码把降低unsafe用量、往地道 Rust 风格靠拢的工作留到 v1.4 发布后再逐步重构。这两个决策定了调剩下的都是战术细节。四、工程力学50 个 Dynamic Workflow × 64 个 Claude × 11 天Jarred 用了约 50 个 Dynamic Workflow连续运行 11 天。每个 workflow 是一个循环——pop task → implement → review → apply feedback覆盖了生成 PORTING.mdZig 模式→Rust 模式的映射文档LIFETIMES.tsv全代码库结构体字段的生命周期分析机械翻译 1,448 个.zig文件到.rs修复每个 crate 的编译错误让bun test、bun build等子命令跑起来让整个测试套件通过峰值时开了 4 个 workflow每个独占一个 git worktree各跑 16 个 Claude总计 64 个并行实例。峰值产出每分钟 58 次提交、1,300 行代码。中间踩了多个坑。Claude 会互相 git stash 踩踏会写冗长的注释来 justify workaround会在编译错误阶段选择 stub out 而非真正修复。Jarred 的策略是edit the workflow prompt不手修代码——告诉 workflow「禁止 git stash」「禁止 cargo」「禁止长注释」问题就自动消失。# 每个 Workflow 的循环逻辑伪代码whiletasktodo_list.pop(): resultimplementer(task)feedbackawait adversarial_review(result)# 至少 2 个apply_feedback(feedback, result)五、核心机制实现者-对抗性审查者分离这是整篇文章最值得抄走的设计。Jarred 的类比很直接写代码的人天然想让代码尽快合并这个动机会让他对自己代码的问题视而不见。Claude 也一样——负责实现的 Claude 想让代码通过负责审查的 Claude 的唯一任务就是挑毛病。配置很简单1 个实现者 至少 2 个对抗性审查者。审查者只拿到代码 diff看不到实现者的推理过程被明确告知「默认这段代码是错的」。文章公开了三个被这套机制真实拦截的 bug场景1异步关闭的悬空指针 实现者把持有管道的 Box 传给了异步 uv_close。 Box 在函数返回时提前释放libuv 回调时就是 use-after-free 双重释放。 审查看穿后改用 Box::leak 处理。 场景2负数时间戳的 nsec 溢出 实现者用 trunc()拆分浮点秒数到 timespec。 对1970年之前的负数文件时间算出非法的负 nsec。 审查者建议换用 floor()。 场景3unwrap_or 的立即求值陷阱 CSS color-mix()解析用 unwrap_or 处理百分比缺省值。 unwrap_or 参数立即求值在应跳过时提前 panic。 审查者建议换成惰性求值的 unwrap_or_else。三个 bug 都能正常编译、看起来也都合理——如果没有专门找茬的第二个 Claude大概率被直接合入主干。这套机制是这次迁移质量的关键保障。六、三阶段管线机械翻译 → 编译错误 → 测试全绿Phase A — 机械翻译。先做 3 个文件的试迁移验证流程然后扩展到 1,448 个.zig文件。由于 Bun 的 git 仓库太大最终方案是 4 个 worktree 各 16 个 Claude。Phase B — 修复 ~16,000 个编译错误。最难的问题是循环依赖。Zig 代码库是单编译单元1 个 crate迁移时拆成 ~100 个 crates循环依赖产生了海量错误。额外跑了一个 workflow 来分类代码应该放哪个 crate。修复时按 crate 分组每组找 1 implementer 2 reviewers 1 fixer 处理。# Phase B 的工作队列16,000 编译器错误 → 按 crate 分组 →64个 Claude 并行修复 每个 crate:cargocheck → 修复 →2个审查者 →1个应用者Phase C — 让测试套件全绿。测试套件包含内存泄漏测试、集成测试next dev热更新的长时间测试、压力测试耗尽 TCP socket、读写 GB 级数据、spawn 10k 进程。使用了systemd-runcgroups做隔离。Linux x64 的 60 个测试分片先绿Windows 最后才通过。从第一个测试绿到全平台全绿用了约 3 天。七、核心数据与成本指标数值Zig 代码不含注释535,496 行Rust 代码1,009,272 行耗时11 天5/3 → 5/14 合并入主干并行 Claude 实例64 个4 worktrees × 16总提交6,778 次峰值产出58 提交/分钟1,300 行/分钟API 成本$165,000Token 消耗5.9B uncached input 690M output缓存读取72B cached input tokens删减测试用例0 个等效人力~3 人年全周期冻结功能开发二进制体积缩减~20%已知回归19 个全部已修复Rust unsafe 占比~4%13,000 个 unsafe 关键字等效 3 人年、$16.5 万 API 成本、11 天——这个 ROI 放在任何商业决策里都是压倒性的。八、迁移后成果与 19 个回归合并后的成果内存泄漏彻底消除。所有之前靠 ASAN 和模糊测试「事后发现」的问题在安全 Rust 里直接是编译错误二进制体积缩减约 20%多平台吞吐量提升24/7 覆盖引导模糊测试已上线覆盖所有解析器JS/TS/JSX/CSS/JSON5/TOML/…自动提交 PR11 轮 Claude Code Security 安全审查完成并修复所有发现19 个回归的根因值得关注——大多来自「语法相同但语义不同」// Zig: assert 是函数参数在 release 中也执行 assert(try dev.client_graph.insertStale(...));// Rust: debug_assert!是宏release 中整行擦除 debug_assert!(dev.client_graph.insert_stale(...)?...);// → insert_stale 在 release 中不执行HMR 损坏其他回归包括bytemuck::cast_slice对奇数长度 slice 直接 panicZig 的reinterpretSlice会忽略尾字节、编译器检查更严格导致的边界差异。九、给实践者的启示这次迁移不仅是技术案例更是 AI Agent 工程化的里程碑。几点值得思考的1. 对抗性审查是质量的关键。不是「AI 写代码」厉害是「AI 写 AI 审」这个协作模式厉害。实现者和审查者分离、分开上下文窗口是目前最适合大规模 LLM 代码生产的模式。2. 工作流的 prompt 比代码更重要。Jarred 几乎所有问题解决方式都是 edit the workflow prompt——告诉 Claude 不要做什么而不是手动修复输出。「edit the loopnot the output」本身就是工程方法论。3. 测试套件是最后的防线。0 被删减、138 万 expect 断言——没有这套百万级测试体系没有人敢合并 100 万行 AI 代码。测试覆盖率不是锦上添花是 AI 代码生产的必要基础设施。4. 成本已经不是拦路虎。$16.5 万做 3 人年的工作量在商业决策层面已经不需要犹豫。真正的问题不是「贵不贵」而是「你的代码库有足够的测试覆盖率来兜底吗」。5. 语法相同 ≠ 语义相同。19 个回归几乎全是跨语言「看起来一样但行为不同」的陷阱——debug_assert! 的宏语义、不同语言的边界检查、slice 处理的直觉差异。原文https://bun.sh/blog/bun-in-rustJarred Sumner2026-07-08