Bun 从 Zig 重写到 Rust

Simon Willison··作者 Simon Willison

关键信息

一个关键条件是 Bun 的测试套件使用 TypeScript 编写,因此可以充当新实现的符合性测试套件。这次重写采用了受监控的代理循环、对抗性审查以及修正生成流程而不是手工逐个修 bug 的方式;文中还提到合并前的 token 使用量为 59 亿未缓存输入 token、6.9 亿输出 token 和 720 亿缓存输入读取。

资讯摘要

Jarred Sumner 的这篇文章把 Bun 从 Zig 重写到 Rust 的过程,描述成一次技术迁移,也是一则现代代理辅助工程的案例。文章首先承认 Zig 让 Bun 走到了今天,但项目积累下来的 bug 列表已经让崩溃和内存问题变得越来越令人头疼。Sumner 认为,直到最近,对于这样规模的项目来说,语言选择几乎是一次性的决定,而前沿模型驱动的编码代理改变了这种局面。之所以选择 Rust,核心原因是 Bun 的很多 bug 都与内存管理有关,包括 use-after-free、double-free 以及错误路径里忘记释放内存。 在安全 Rust 中,这些问题会直接变成编译错误,而清理工作可以通过 Drop 自动完成。一个重要的前提是,Bun 的测试套件是用 TypeScript 写的,因此可以充当这次重写的符合性测试套件。

借助这一点,代理系统可以自动完成从 Zig 到 Rust 的初始翻译,而且最早的实验还是用更早一代的模型做的。大约 11 天里,Sumner 持续监控这些工作流,人工检查输出中的问题,并在流程需要改进时让 Claude 去修改生成循环本身。文章强调,真正难点不只是生成代码,而是如何通过测试驱动的信心和对抗性审查,去审核和稳定一百多万行新增代码。如今 Rust 版 Bun 已经在 Claude Code 中运行了将近一个月,自 6 月 17 日发布的 v2.1.181 起开始使用。除了 Linux 上启动速度提升约 10% 外,这次切换对用户几乎没有可见影响,而作者认为“没新闻”本身就是好消息。文中还提到,合并前的模型调用规模非常大,包括 59 亿未缓存输入 token,估算按 API 价格约合 16.5 万美元。

资讯正文

<strong><a href="https://bun.com/blog/bun-in-rust">用 Rust 重写 Bun</a></strong>

Jarred Sumner 一直在承诺写这篇博文(<a href="https://x.com/jarredsumner/status/2053063524826620129">自 5 月 9 日起</a>),讲述他把 Bun 从 Zig 重写到 Rust 的过程,这个等待时间比他完成重写所花的时间还要长得多。

说实话,这等待是值得的。这是一篇对一项极其复杂的 agentic 工程的详细描述,其中包含动态工作流、试运行、对抗性审查以及各种其他有趣的技巧。

Jarred 在文章的前半部分称赞了 Zig,认为正是它让 Bun 走到了今天。然后我们进入了这篇文章的一个核心观点,以下引文中的强调是我加的:

<blockquote>

我们那份 bug 修复清单让人很难受,而我也厌倦了每晚睡觉前还要担心 Bun 会崩溃。我并不因此责怪 Zig——其他 Zig 用户没有我们遇到的那些问题,而把 GC 和手动管理内存混在一起,对软件来说本来就不是一种常见到足以让任何语言专门为之设计的需求。如果没有 Zig,我们不可能走到这一步,我会一直心怀感激。**直到最近,对于 Bun 这样的项目来说,编程语言的选择还是一个单向决定。**

</blockquote>

众所周知,你永远不应该停下来,把一大块软件从头到尾推倒重写。Joel Spolsky 早在 2000 年 4 月就在 <a href="https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/">Things You Should Never Do, Part I</a> 里强调过这一点!

由当今前沿模型驱动的编码代理改变了这套计算。

为什么选择 Rust?归根结底,是内存管理方面的那些挑战:

<blockquote>

那份清单里很大一部分 bug 都是 use-after-free、double-free,以及在错误处理路径上“忘记释放”。在安全的 Rust 中,这些都会变成编译器错误,以及类似 RAII 的借助 <code>Drop</code> 的自动清理。

</blockquote>

这次重写的一个关键促成因素是,Bun 的测试套件是用 TypeScript 写的,这意味着它可以充当<a href="https://simonwillison.net/tags/conformance-suites/">一致性测试套件</a>。这让一个 agent harness 能够自动化完成从 Bun 到 Rust 的大部分初始移植工作,最初这只是一次实验,用来试用我们如今以 Mythos/Fable 名义访问到的那个更早版本的模型。

<blockquote>

一开始,我并不指望它能奏效。几天之后,测试套件中相当高比例的测试开始通过,我也看到了新 Rust 代码与原始 Zig 代码库之间的高度对应。我的看法从“值得一试”变成了“我要把它合并进去”。[...]

在那 11 天里的大部分时间(以及之后),我都在监控工作流——手动阅读输出以检查问题和 bug,并提示 Claude 修改循环来修复问题。

你要如何审查一个新增了 100 多万行代码的 PR?你又该如何开始建立起那种信心,才能负责任地合并大量由 LLM 编写的代码?

一个与语言无关、包含一百万条断言的测试套件,对代码进行对抗性审查;而当确实出问题时,修复的是生成代码的流程,而不是手工去修补代码。

</blockquote>

Bun 的新实现现在已经在 Claude Code 中上线近一个月了:

Claude Code v2.1.181(6 月 17 日发布)及之后的版本使用的是 Bun 的 Rust 移植版。在 Linux 上,启动速度快了 10%,除此之外,几乎没人注意到什么变化。平平无奇就是好事。

在 Anthropic 工作的一个好处是,你不需要为自己的 token 付费——而当预估成本高达 165,000 美元时,这一点就很方便了!

合并前,这项工作消耗了 59 亿个未缓存输入 token、6.9 亿个输出 token,以及 720 亿次缓存输入 token 读取——按 API 定价计算,大约是 165,000 美元。

在协调一致的并行代理帮助下,承接这样一个极其雄心勃勃的项目,这整件事是一个非常有趣的案例研究。

来源与参考

  1. 原始链接
  2. Rewriting Bun in Rust

收录于 2026-07-10