作者统计了Bun从Zig迁移到Rust前后共2981个issue,发现重写后特定bug类型显著减少,但 Canary 版本稳定性仍需关注,提供了可验证的数据集和交互报告。
5 月 14 日,Bun 合入了 PR #30412。一个 PR:新增 1,009,257 行代码,修改了 2,188 个文件。整个运行时在 11 天内从 Zig 移植到 Rust,参与的大约是 50 个并行 Claude Code 工作流,API 成本约 165,000 美元。Jarred Sumner 估计一个人类团队需要一年才能完成。
各方反应正如你所料。Zig 的作者 Andrew Kelley 称这是"百万行未经审查的垃圾"。Rust 社区称这是未来。三个月的争论,据我观察,双方都没有拿出实际数据。
所以我来了。从合并前六个月到上周,对 oven-sh/bun 提交的所有 issue:2,981 个,按合并时间戳按周分组,每个都根据报告者运行的构建版本分类。数据集和脚本放在这个仓库里,如果想核实我的工作,那里还有一份更枯燥的交互式报告,包含每张图表。
这次重写的卖点是内存安全。Bun 的追踪器被 use-after-free 和 double-free 崩溃淹没,而在安全的 Rust 中这些是编译错误。Sumner 用一句话概括了整个论点:"编译器错误比风格指南更好的反馈循环。"
Canary 是验证这个说法的地方,因为 canary 是唯一一个实际发布过 Rust 构建的渠道。同样的渠道、同样的自选用户——运行预发布版本的用户,5 月 14 日之前是 Zig 构建,之后是 Rust 构建。分割点异常清晰:我检查了六个月 pre-merge issue 中每个版本字符串,没有一个标注了 1.4.x 的 Bun 构建。grep 找到九个匹配项,而这九个都是 elysia 1.4.x 这样的库版本。1.4 版本线在合并当天早上之前根本不存在于用户端。
canary 上的 bug 报告从每周 5.9 个上升到 20.7 个。我不把这解读为"Rust 让 bug 翻了三倍",因为同一时刻还有两件事发生了变化:canary 成为获取新引擎的唯一途径,所以用户群扩大了,而且这个 PR 实际上是在请求人们提交 issue。报告量 = 曝光量 × 缺陷率 × 报告意愿,而你只能观察到最终结果。
但比率不在乎人口规模,它们很固执:
重写前,43.5% 的 canary bug 报告最终以已修复关闭。重写后:41.9%。
每周修复的 canary bug:重写前 2.6 个,重写后 8.7 个。与报告洪水量成正比,没有更好。
所有 bug 报告的修复时间中位数:重写前 2.7 天,重写后 3.2 天。
同一台机器,三倍输入。
在你提出明显反对意见之前:我对分类器做了压力测试。一条更严格的规则——只接受真实 Bun 上下文中的版本字符串(构建哈希,或紧挨着模板中"你运行的是哪个版本的 Bun?"的版本)——使计数移动了不到 1%,且两个修复率在小数点后一位完全相同。如果有什么不同的话,它让增幅稍微变大了一点,从 3.5 倍变成 3.6 倍。仓库中有鲁棒性脚本和独立验证,从冻结数据重新推导所有 31 个已发布数字。
与此同时,围绕代码的过程陷入了僵局。去年 11 月,只有 1-3% 的新 Bun issue 没有标签;分类在春季已经开始出现漏报,而自合并以来,大约一半的新 issue 根本没有任何标签。Bun 在 5 月 14 日之前的六个月发布了 12 个稳定版。此后:零个,89 天。Bun 在 2024-2026 年间任意两个版本之间的最长间隔是 27 天。今天每个稳定版用户仍在运行这个项目据说已经放弃的 Zig 二进制文件。
这是谨慎还是瘫痪,我无法从外部判断。很可能两者兼而有之。
一旦你注意到它发生的条件,平稳的修复率就变得有趣了。
移植是对刚性语言最友好的工作。规格已冻结:表现得和旧的 Bun 完全一样。百万级别的 TypeScript 测试套件坐在那里作为预言机,每一步都在检查。11 天里,需求没有移动。甚至无法忍受 Rust 的人也会承认这个领域属于它。一篇被广泛分享的《在 Rust 游戏开发三年后离开》,作者背后有超过 10 万行 Rust 经验,直白地说:"Rust 非常适合那些底层算法领域,在那里人们确切地知道问题是什么,只需要解决它。"
所以 Rust 获得了理想的条件,加上一个 AI 来吸收每一个借用检查器的抱怨,最终交付了与 Zig 时代相同的修复率和处于昏迷状态的发布管道。
这就是我停止报告、开始争论的地方。
我花了十多年构建软件,大多数是产品,几乎没有像那次移植。没有预言机。规格是一段 Slack 帖子和一个 mockup。需求在用户第一次接触功能时就变了,然后再次改变。一半的工作是弄清楚我们应该构建什么,通常是先构建错误的东西。
这就是语言刚性会造成伤害的运行环境,持有这种观点的人不是那些在第一周就被借用检查器阻挡的初学者。游戏开发文章再说一次:"借用检查器在最不方便的时候强制重构。"John Nagle——Nagle 算法的作者,在元宇宙客户端中写了大约 45k 行 Rust——表示赞同:"有些变更需要进行大量管道工作是很常见的",并指出使用 C#/Unity 的团队在同样问题上移动 速度比他更快。一位在 Epic 和 Valve 有 25 年经验的资深人士在 Rust 上花了 14 个月构建游戏,在 Unity 中用六周重做,然后上线了。Graydon Hoare——Rust 的创始人——在 2023 年写道,已上线的 Rust 远非他想要的语言,他曾反对显式生命周期、一等借用和 trait 系统。而在 Rust 自己的年度调查中,用户对语言未来的最大担忧是"Rust 变得太复杂",占 43%。
Rob Pike 因为 Go 简洁的理由承受了无穷无尽的非议:"我们的程序员是 Google 员工,他们不是研究人员……他们没有能力理解一门卓越的语言,但我们想用他们来构建好的软件。"每次我重读这段话,它听起来都不像侮辱,而更像是语言设计中唯一锚定于团队实际工作方式的陈述。你的同事很忙且分心。你也是,我也是。一门假设并非如此的语言正好在截止日期和需求变更同时到来时开出账单。
反证是真实的,我不会隐瞒。Google 报告 Android rollout 中 Rust 变更回滚的频率比 C++ 低 4 倍,review 时间少 25%;在 1,000 多名开发者中,他们没有发现生产力损失。Dropbox 用 Rust 重写了同步引擎——他们拥有的边缘情况最多的东西——并把这次赌注称为力量倍增器。
然而,看看这些胜利有什么共同点。Android 平台代码和文件同步引擎是世界上规格最精确的软件之一。不变量在任何人写第一行代码之前就已知道。这场争论中的两方在边界上达成了一致却没有意识到他们一致:当你确切知道自己在构建什么时,刚性是脚手架。当你不确定时,你每冲刺一次都在为之付息。
问题从来不是"Rust 好吗"。而是你的路线图中有多大比例是规格冻结的执行,有多大比例是"发布两次后我们才会理解这个功能"。对这个分割要诚实。在我见过的大多数团队中,是一份执行配五份摸索。
支持最大刚性的最新论点:语言难度不再重要,因为 agent 写代码,编译器验证它们。这背后有真正的研究。一 LLM 在 rustc 错误信息上循环大约能自行修复 74% 的真实世界编译错误。用类型系统约束模型的解码,编译错误下降超过一半。
Bun 是迄今为止对这一论点最大规模的实地测试,结果是单方面的:机器那一半奏效了,人类那一半没有。Claude 让借用检查器满意了一百万行代码。然后分类崩溃了,review 成为瓶颈,三个月来没有任何东西发布。Kelley 的讽刺在这里落地——不管你喜欢 Zig 还是其他:"在 Zig 代码中捕获 bug 是不够的,但在[一]百万行未经审查的垃圾中捕获 bug 是够的?"
值得补充的是:Armin Ronacher,多年在 Sentry 生产环境中运行 Rust,他不断用编码 agent 做实验,推荐 Go 而不是 Rust。在他的测试中,在 agent 循环中放入严格类型检查反而让结果变差。
编译器可以证明代码做了什么。它无法证明那是代码的用途。第二个问题是全部工作,它留在人类这边,没有哪种语言刚性可以缩小它。
先披露利益相关,因为这个故事浸透了它们:Anthropic 在 2025 年 12 月收购了 Bun,重写运行在预发布 Claude 模型上,Sumner 的速度和成本数字是自我报告的,我也是用 Claude 的帮助完成这个分析的。
但截至今天的数据说的是:在刚性语言将获得的单次最有利设置下——冻结规格、完美预言机、不知疲倦的 AI 劳动力——它在 bug 处理方式上没有产生任何可衡量的改善,而周围的人类失去了发布能力。你的项目没有这些优势之一。你的规格每周都在变。你的预言机是 PM 记得同意过的任何东西。你的测试套件不是百万条断言。
当问题真正被固定时,选择严格、复杂的语言。它会在那里为你守住防线。对于其他一切——我认为这是大多数软件——复杂性是对每次变更征收的税,编译器的确定性始终是关于昨天需求的确定性。
数字、脚本和完整研究在仓库里。如果你认为我读错了数据,评论区等着你。