开发者生态
morning
史上最高调的AI重写:Claude花11天搞定Bun,创始人花一个月才敢交底
2026-07-10
1 阅读
约10分钟阅读
Tina
字号:
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 版本。 成果:从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的bug修复清单中,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,从内存泄漏到崩溃到颜色显示错误的帮助文本都得到了解决。 从体积上,结合 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秒。 而 Claude Code在基于Rust Bun发布后,Linux上的启动时间从517ms降至464ms,快了约10%。 方法: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来加快编译速度,循环依赖导致
这篇文章对您有帮助吗?
订阅66必读
每日精选科技资讯,直达你的邮箱