编程 当 Bun 用 AI 亲手换掉自己的心脏:从 Zig 到 Rust 的 11 天大迁徙,揭示了软件工程的哪些新真相?

2026-07-11 09:16:55 +0800 CST views 13

当 Bun 用 AI 亲手换掉自己的"心脏":从 Zig 到 Rust 的 11 天大迁徙,揭示了软件工程的哪些新真相?

引言:一场"自杀式"重写,一个时代的隐喻

2026年5月,编程界上演了一出荒诞又深刻的戏码。

Bun——这个以 Zig 语言构建、号称比 Node.js 快数倍的 JavaScript/TypeScript 全栈运行时——在被它自己的用户 Claude Code(Anthropic 的 AI 编程工具)因内存泄漏问题拖垮后,决定亲手把自己从 Zig 重写成 Rust。

整个过程仅用了 11 天,涉及 1448 个文件的机械翻译、近 100 万行新增代码6755 次提交。测试套件达到 99.8% 通过率,最终直接合并进主分支。

PR #30412 的代码量太大,以至于直接把 GitHub 页面搞崩了

这不是一个普通的技术八卦。这件事背后,藏着 2026 年软件工程领域最值得深思的几个命题:

  1. AI 辅助编程的规模化实践边界在哪里?
  2. 一门系统级语言(Zig)的工程化困境与 Rust 的不可替代性
  3. Anthropic 收购 Bun 背后的战略逻辑,以及这对 Claude Code 意味着什么
  4. 当 AI 能批量生产代码时,"代码所有权"和"代码质量"如何重新定义?

本文将从技术、工程、组织和行业四个维度,把这件事彻底拆透。


一、背景:为什么 Bun 会选择 Zig,又为什么最终"背叛"了它

1.1 Zig 的野心与陷阱

Bun 项目始于 2021 年,创始人 Jarred Sumner 选择 Zig 作为核心实现语言,这在当时是一个非常有争议但又极具吸引力的选择。

Zig 的核心设计哲学是"没有隐藏控制流、没有隐藏内存分配、没有宏"——它比 C 更透明,同时保持了与 C 几乎无缝的互操作性。对于一个 JavaScript 运行时来说,这意味着:

  • 零成本抽象:可以写出接近手写 C 的性能,同时保持代码可读性
  • 精确的内存控制:运行时完全掌控何时分配、释放内存
  • 编译速度极快:比 Rust 快一个数量级,开发迭代体验好

Jarred Sumner 曾在多个场合表示,Zig 是构建高性能 JavaScript 运行时的"完美语言"。从技术上看,这个判断没有错——Zig 版本的 Bun 在性能基准测试中确实表现优异,JavaScript 执行速度、HTTP 服务器吞吐量、包安装速度都大幅领先 Node.js。

然而,工程现实给理想主义上了一课。

Zig 是一门极其年轻且仍在快速迭代的语言。从 0.9 到 0.14,Zig 经历了多次破坏性变更,每一次编译器升级都可能让既有代码无法编译。更关键的是,Zig 的工具链和生态远未成熟——没有像 Cargo 那样可靠的包管理器,没有稳定的语言服务器,调试工具链相当原始。

当项目规模从几万行扩展到接近百万行时,这些问题被急剧放大。

1.2 内存泄漏:埋进地基的定时炸弹

对于一个 JavaScript 运行时来说,内存管理的正确性是生命线。每天处理数十亿次请求的运行时,任何内存泄漏都会以指数级放大。

然而,Zig 虽然提供了精确的内存控制能力,却没有编译器层面的强制保障。手动内存管理的每一步都需要开发者自己保证正确性。随着代码规模扩大,人工审查的难度呈几何级增长,而 Bun 的内存泄漏问题在生产环境中频繁出现。

最讽刺的蝴蝶效应来了:

Anthropic 在 2025 年 12 月收购了 Bun。之后,Bun 深度嵌入了 Claude Code 的技术栈——Claude Code 内置了 Bun 运行时来执行 JavaScript/TypeScript 代码。

然后:Claude Code 频繁因 Bun 的内存泄漏而崩溃。

一个被自己的内存泄漏问题坑惨的 AI 工具,去重写那个有问题的工具——这件事的荒诞程度,大概连科幻小说都不敢这么写。


二、技术解析:一次"纯机械"的大迁徙是怎样完成的

2.1 为什么选择 Rust 而不是其他语言

在确定"必须重写"之后,Bun 团队面临一个技术选型问题:换成什么语言?

选项分析:

语言优势劣势
Rust内存安全保证、优秀的工具链(Cargo)、活跃生态、编译时消除 dangling pointer/buffer overflow编译速度较慢、async 生态复杂
Go简单、goroutine 并发模型成熟、编译快运行时 GC 延迟、不够底层
C++极致性能、完全控制内存安全完全依赖程序员、工具链原始
Zig性能好、与 C 无缝互操作语言不稳定、生态弱

最终选 Rust,核心原因只有一个:Rust 的编译器提供了"内存安全的强制保证"

Rust 的所有权系统(Ownership)和借用检查器(Borrow Checker)能在编译时捕获 use-after-free、data race、buffer overflow 等常见内存安全漏洞。对于 Bun 这种基础设施级软件,这个特性是无价的。

值得注意的是,Jarred Sumner 明确表示:Bun 重写后依然不使用 async Rust。这说明团队对 Rust 的异步运行时复杂度有清醒的认识,选择了一条更保守但更可控的技术路径。

2.2 AI 翻译流水线:对抗工作流的工程实践

这次重写最令人震惊的不是结果,而是过程

Jarred Sumner 事后透露,这次重写采用了"对抗工作流"(Adversarial Workflow):

"整个讨论有点反应过度了。300 多条评论,全都围绕一堆根本还跑不起来的代码。我们并没有决定一定要重写。而且这些代码最后被全部扔掉的概率其实非常高。我只是很好奇:一个真正可运行的版本到底会是什么样、用起来感觉如何、性能如何,以及让它通过 Bun 的测试套件并真正变得可维护,到底会有多难。"

具体分工如下:

┌─────────────────────────────────────────────────────────┐
│                    AI 翻译流水线                          │
├──────────────┬──────────────────────────────────────────┤
│ 翻译Agent    │ 将 Zig 文件机械翻译为 Rust 草稿           │
│ 验证Agent    │ 对照 Zig 代码和 Rust 规范做一致性验证      │
│ 修复Agent    │ 处理类型不匹配、lifetime 报错              │
│ Audit Agent  │ 审查所有 unsafe 代码块                     │
│ Windows Agent │ 专门处理 Windows 平台的兼容性 bug          │
└──────────────┴──────────────────────────────────────────┘

这个流水线的关键洞察是:它没有试图让 AI"理解"代码,而是让 AI 做一个高吞吐量的翻译机器。 代码的语义正确性由原有的 Zig 测试套件来保证,AI 的任务只是把 Zig 语法"变成" Rust 语法。

2.3 机械翻译的工程挑战:99.8% 通过率意味着什么

最终数字:

  • 翻译文件数:1448 个 Zig 文件
  • 提交数:6755 次
  • 新增代码:约 96 万行
  • 测试通过率:99.8%(原有测试套件)
  • 耗时:11 天(另有说法是 6 天核心冲刺)

99.8% 的通过率听起来接近完美,但 Bun 团队和社区都清楚:测试通过率不等于代码质量等于原版

一些开发者在社区中提出的核心质疑是:

"当 AI 生成代码的速度远远超过人类审查代码的速度时,我们该如何证明这些代码真的值得信任?"

这个问题没有简单的答案。测试套件能保证行为一致性(输出结果相同),但不能保证实现质量(没有隐藏 bug、没有性能退化、没有潜在的未定义行为)。

2.4 代码量"打爆 GitHub":一次 PR 的工程奇观

PR #30412 包含了超过 100 万行新增代码。这个量级直接导致 GitHub 的 diff 渲染页面无法正常加载——GitHub 的前端根本没有考虑过有人会提交如此规模的重写。

# PR 信息
PR: #30412
Title: [RFC] Rust rewrite of bun runtime
Files changed: 1448
Commits: 6755
Additions: ~960,000 lines
Deletions: ~920,000 lines (Zig code removed)

这个 PR 本身就是一个工程奇观,它让我们意识到:GitHub 作为一个代码托管平台,其前端交互设计隐含了"人类审查代码"的假设。当代码由 AI 批量生成时,这个假设不再成立。


三、工程哲学:为什么"保持架构不变"是这次重写最聪明的决定

3.1 不重写架构,只替换语言

很多大型重写失败的案例,问题不在于语言选择,而在于把重写当成了重新设计。团队在重写的过程中忍不住想要"修缮"既有的架构缺陷,最终导致两个系统并行演化,永远无法收敛。

Bun 的 Rust 重写采取了一个极其克制的策略:完全保留原有的架构设计、数据结构、模块边界。

  • 相同的调度器设计:保留了原有的工作窃取调度器
  • 相同的数据结构:JS 对象模型、字符串实现、V8 集成方式不变
  • 相同的 FFI 策略:继续使用 Zig 的 C interop 模式(通过 cbindgen 风格的 Rust-C 绑定)
  • 相同的第三方依赖策略:Bun 素来以"少用第三方库"著称,Rust 版本延续了这一理念

这意味着,这次重写本质上是一次编译器替换,而不是一次架构重构。这是一个非常重要的工程判断。

3.2 性能实测:Rust 版本真的更好吗?

根据 Bun 官方公布的基准测试数据:

基准项Zig 版本Rust 版本差异
HTTP 吞吐量基准+2% ~ +8%持平或略好
冷启动时间基准-3ms略快
二进制体积基准-3 ~ -8 MB缩小
内存占用(长期运行)基准显著降低大幅改善
Windows 兼容性有 bug已修复大幅改善

最关键的改进不是峰值性能,而是长期运行的内存稳定性——这正是这次重写的原始动机。Rust 编译器在编译期的内存安全检查,从根本上消除了那类需要运行很长时间才能触发的"慢速内存泄漏"。

3.3 二进制体积缩小:Rust 优化带来的意外红利

Rust 版本比 Zig 版本二进制体积小 3-8 MB,这是一个意外的收获。

分析其原因:

  1. Rust 的链接模型更高效:相比 Zig 的激进内联策略,Rust 的 LTO(Link Time Optimization)在链接阶段能更全局地做内联和死代码消除
  2. panic 处理更紧凑:Rust 的 panic 默认是 panic-on-abort(不展开栈),比 Zig 的默认展开更省空间
  3. 目标文件格式:ELF/Mach-O 中的调试信息压缩更好
// Rust 版本的 panic 策略(嵌入式友好)
// Cargo.toml
[profile.release]
panic = "abort"           // 禁用栈展开,减小二进制体积
lto = true                 // 链接时优化
codegen-units = 1          // 最大优化
opt-level = "z"            // 优化体积而非速度
strip = true               // 发布时去掉调试符号

四、Anthropic 收购背后的战略棋局

4.1 为什么 Anthropic 要买一个 JavaScript 运行时?

2025 年 12 月,Anthropic 收购 Bun 的消息让很多人困惑:AI 公司为什么要买一个 JavaScript 运行时?

答案藏在 Claude Code 的技术栈里。

Claude Code 是一个 AI 编程助手,它需要:

  • 快速执行用户提交的代码片段(沙箱执行)
  • 处理 npm 包依赖(npm install 在 Node.js 上很慢)
  • 运行 JavaScript/TypeScript 测试套件

Bun 在这些场景下有决定性优势:包安装速度是 npm 的 10 倍,HTTP 服务器性能比 Node.js 高数倍,冷启动时间接近零。

对于一个 AI 编程工具来说,每一次用户交互都可能触发一次代码执行,速度差异直接等同于用户体验差异。

Anthropic 的商业逻辑:

Claude Code(需要极速代码执行)
    ↓
Bun(极速 JavaScript 运行时)
    ↓
内存泄漏导致 Claude Code 频繁崩溃
    ↓
Anthropic 选择:买下 Bun,自己修复
    ↓
Claude AI + Claude Code + Bun = AI 原生开发工具链

4.2 Claude Code 内置 Bun 运行时:这对用户意味着什么

随着收购完成,Claude Code 已经开始在 beta 阶段内置 Bun 运行时。这意味着:

对开发者(用户)的好处:

  • 代码执行速度更快
  • 包安装几乎瞬间完成
  • 依赖解析错误减少

对 Anthropic 的战略好处:

  • 不再依赖外部维护者的节奏,可以自主控制关键依赖的稳定性
  • 可以在 Bun 运行时中嵌入更多 Claude 特有的运行时优化
  • 为未来的"Claude 原生"JavaScript 开发环境奠定基础

风险:

  • AI 公司控制核心基础设施引发社区担忧
  • Bun 开源项目的治理独立性受到影响

五、AI 编程的新范式:对抗工作流揭示的工程真相

5.1 AI 翻译的适用条件:什么项目可以做,什么不行

Bun 的案例给我们提供了一个非常清晰的判断框架:

AI 机械翻译适用于满足以下条件的项目:

  1. 有完整的测试套件:Bun 原有测试覆盖了 99.8% 的行为边界
  2. 有明确的规范:JavaScript 语义由 TC39 标准定义,Bun 只需实现正确行为
  3. 有可机器读取的接口契约:模块边界清晰,类型签名明确
  4. 目标语言与源语言有良好对应关系:Zig → Rust 的类型系统映射相对直接
  5. 项目规模足够大:人工重写成本极高,AI 的高吞吐量优势明显

不适用于:

  • ❌ 需要理解业务逻辑的遗留代码(没有测试、语义模糊)
  • ❌ 高度创新的项目(没有规范可循,需要真正的设计判断)
  • ❌ 高度政治性的代码(涉及多方利益、没有唯一正确答案)

5.2 人类的角色:从"写代码"到"审代码"

Jarred Sumner 的另一句话值得玩味:

"未来开源可能禁止人类提交代码。"

这句话当然是一种夸张的修辞,但它指向了一个真实的趋势:在 AI 高效产出代码的时代,人类工程师的核心价值正在从"编写"转向"判断"。

具体来说:

传统模式AI 辅助模式
工程师写代码AI 生成代码候选
工程师 review 代码工程师判断质量
工程师跑测试测试套件自动验证
工程师设计架构工程师定义架构约束,AI 填充实现
工程师 debugAI + 工程师协同定位

这不是说人类被替代了,而是说人类从"执行层"上升到了"决策层"。这个转变要求工程师有更强的架构能力、更深的领域理解、更精准的判断力。

5.3 99.8% 通过率之后的 0.2%:AI 时代的测试哲学

测试套件 99.8% 的通过率,意味着还有 0.2% 的测试用例失败了——或者更准确地说,有 0.2% 的场景新代码的行为与原版不一致。

这 0.2% 可能是:

  • 竞态条件:只在特定时序下出现的 bug,测试套件没有覆盖
  • 边缘情况:输入超出正常范围的 corner case
  • 平台差异:Windows 特定行为,Unix 测试覆盖不了

对于生产级软件来说,这 0.2% 可能是灾难性的。

这里引出了一个 AI 时代的核心工程问题:

测试套件的价值被重新定义。 在 AI 生成代码的场景下,测试套件不仅验证当前实现的正确性,还承担了验证 AI 翻译等价性的新使命。这意味着测试套件的覆盖率、边界 case 的设计、对罕见场景的覆盖,都变得比以往任何时候都更重要。


六、Bun 的未来:从"工具"到"平台"的蜕变

6.1 Rust 之后:性能优化进入深水区

Bun 团队已经明确表示:Rust 重写不是终点,而是新起点。Rust 版本还处于 canary 频道,优化工作仍在进行中。

下一步的优化方向:

  1. SIMD 加速:利用 Rust 的 SIMD intrinsics 加速字节码解释器
  2. Profile-Guided Optimization (PGO):基于真实运行数据做二次编译优化
  3. JIT 编译器改造:Zig 版本的 JIT 有很多历史包袱,Rust 版本有望重构出一个更干净的 JIT

6.2 Claude CoPilot:AI 原生开发工具链的雏形

Anthropic 收购 Bun 的真正野心,可能不只是为了让 Claude Code 不崩溃。

随着 Claude Code 深度集成 Bun 运行时,Anthropic 正在构建一个独特的价值主张:

Claude(推理能力)
    +
Claude Code(Bun 执行环境)
    +
Bun 运行时(极速 JavaScript/TypeScript)
    =
AI 原生开发闭环

在这个闭环中,Claude 的推理、Claude Code 的执行、Bun 的运行时,三者被深度整合,AI 可以在运行时直接感知代码执行的性能数据,并以此优化推理结果。这是任何依赖外部 Node.js 运行时的竞品所无法复制的优势。

6.3 社区反应:开源世界的分裂与焦虑

Bun 宣布 Rust 重写后,Hacker News 和 GitHub 讨论区的反应呈现出明显的两极化:

支持者的观点:

  • "Rust 的内存安全保证对基础设施软件来说是不可拒绝的"
  • "测试套件 99.8% 通过率已经是极高的置信度"
  • "Anthropic 背书意味着更多资源投入,Bun 的未来更光明"

质疑者的观点:

  • "Anthropic 控制了 Bun,这改变了开源治理的本质"
  • "AI 批量生成的代码真的可维护吗?未来还有谁能接手?"
  • "99.8% 测试通过率不等于代码等价的 0.2% 可能是最难发现的隐藏 bug"

这些讨论的本质,其实是一个更大的问题:当 AI 成为代码生成的主要力量时,"开源软件"的含义是否需要被重新定义?


七、实战:用 Bun Rust 版本搭建你的第一个生产级 API

说了这么多理论,让我们来点实际的。Bun Rust 版本(canary 频道)已经开放测试,以下是上手指南:

7.1 安装 Bun Rust 版本(Rust 重写版)

# 通过 canary 频道安装(Rust 版本)
bun upgrade --canary

# 验证版本信息
bun --version
# 输出类似:1.4.0-canary.x (rust-rewrite)

# 确认是否使用了 Rust 运行时
bun --diagnostics

7.2 搭建一个高性能 HTTP API

// server.ts
// Bun Rust 版本的高性能 HTTP 服务器

const server = Bun.serve({
  port: 3000,
  tls: {
    key: "./keys/key.pem",
    cert: "./keys/cert.pem",
  },
  fetch(req) {
    const url = new URL(req.url);
    const pathname = url.pathname;

    // 路由分发
    switch (pathname) {
      case "/api/users":
        return handleUsers(req);
      case "/api/posts":
        return handlePosts(req);
      case "/health":
        return Response.json({ status: "ok", runtime: "bun-rust" });
      default:
        return new Response("Not Found", { status: 404 });
    }
  },
});

async function handleUsers(req: Request): Promise<Response> {
  const db = await Bun.sql.open("sqlite:./data.db");

  if (req.method === "GET") {
    const users = await db.query<User[]>("SELECT * FROM users LIMIT 100");
    return Response.json(users);
  }

  if (req.method === "POST") {
    const body = await req.json<Partial<User>>();
    const result = await db.query(
      "INSERT INTO users (name, email) VALUES (?, ?) RETURNING *",
      [body.name, body.email]
    );
    return Response.json(result[0], { status: 201 });
  }

  return new Response("Method Not Allowed", { status: 405 });
}

async function handlePosts(req: Request): Promise<Response> {
  const db = await Bun.sql.open("sqlite:./data.db");
  const posts = await db.query<Post[]>(`
    SELECT p.*, u.name as author_name
    FROM posts p
    JOIN users u ON p.user_id = u.id
    ORDER BY p.created_at DESC
    LIMIT 50
  `);
  return Response.json(posts);
}

console.log(`Bun Rust 运行时监听端口 ${server.port}`);

7.3 基准测试:Rust 版本 vs Zig 版本

// benchmark.ts - 简单的吞吐量对比
import { bench, run } from "bun";

const server = Bun.serve({
  port: 0, // 随机端口
  fetch(req) {
    return new Response("Hello from Bun " + (process.versions.bun ?? ""));
  },
});

await bench({
  name: "Simple HTTP Response",
  iterations: 100_000,
  runs: 5,
  fn() {
    // 使用内置 HTTP 客户端
    fetch(`http://localhost:${server.port}/`).then(r => r.text());
  },
});

server.stop();
await run();

预期结果(Bun 官方基准):

  • Rust 版本在 HTTP 并发吞吐量上与 Zig 版本持平或略优
  • 长期运行内存稳定性:Rust 版本明显更好(无内存泄漏)
  • 冷启动时间:减少约 3ms

7.4 与 Node.js 的性能对比

# 启动基准测试服务器
bun run server.ts &

# 使用 autocannon 压测
npx autocannon -c 100 -d 10 http://localhost:3000/

# 对比 Node.js(相同代码)
# node server.js &
# npx autocannon -c 100 -d 10 http://localhost:3000/

典型结果对比( Bun 官方数据):

运行时RPS(每秒请求数)延迟 P50延迟 P99内存占用
Bun Rust~95,0001.2ms4.8ms28MB
Bun Zig~93,0001.3ms5.1ms45MB(长期增长)
Node.js 22~42,0002.8ms12ms72MB

八、这场大迁徙揭示的五个工程真相

经过对 Bun 从 Zig 到 Rust 重写的全面拆解,我们可以提炼出以下五个核心工程洞察:

真相一:语言选择是战术问题,架构稳定是战略问题

Bun 的 Zig 选择在初期是正确的——它提供了想要的性能和透明性。但当工程规模突破某个阈值时,语言的成熟度和生态支持开始超越语言的性能特性,成为主要矛盾。

这告诉我们:选语言要看项目所处阶段。初创期可以用激进的新语言快速迭代;成熟期需要切换到有更强保障的主流语言。

真相二:测试套件是新时代的"代码护城河"

Bun 能放心让 AI 批量翻译 1448 个文件,核心前提是有完整的测试套件作为安全网。测试覆盖率越高,AI 介入的空间越大——这个结论对所有想引入 AI 辅助编程的团队都有指导意义。

真相三:AI 编程的规模化临界点是百万行级

Bun 的案例证明:对于百万行级别的代码库,AI 机械翻译的可行性已经得到工程级验证。但这不意味着所有项目都应该这样做——关键是模块边界清晰、接口契约明确

真相四:Anthropic 买 Bun 不是财务投资,是基础设施投资

AI 公司的核心竞争力是模型推理能力,但推理需要载体。当 Claude Code 依赖第三方 JavaScript 运行时并因此频繁崩溃时,控制关键依赖就成了自然选择。这对整个 AI 行业如何处理开源基础设施依赖有深远启示。

真相五:"人类审查代码"的前提正在被动摇

GitHub 能处理 10 万行的人类 PR,但无法优雅地渲染 100 万行的 AI PR。这不是 GitHub 的问题,而是整个工程基础设施都需要重新思考的问题:当代码来源从"人类编写"转向"AI 生成"时,CI/CD、代码审查、权限管理、合规审计的每个环节都需要重新设计。


结语:换心手术成功,但真正的考验才刚开始

Bun 从 Zig 到 Rust 的大迁徙,是 2026 年软件工程领域最具标志性的事件之一。它展示了 AI 辅助编程的最新能力边界,揭示了大型代码库维护的深层挑战,也让我们得以窥见 AI 公司如何将开源基础设施纳入自己的技术栈。

重写完成了,但真正的考验才刚开始:

  • Rust 版本的长期稳定性如何?
  • 社区能否接受 Anthropic 控制的核心基础设施?
  • 0.2% 的未通过测试是否会演变成生产环境中的隐藏炸弹?
  • 当更多项目开始用 AI 批量翻译代码时,"代码所有权"和"代码可维护性"如何重新定义?

这些问题没有现成答案。但有一点是确定的:2026 年的编程世界,已经和 2025 年大不相同了。


本文选题来源:GitHub Trending + OSCHINA 技术社区 + CSDN 开发者社区(2026年7月热点追踪)

推荐文章

Golang在整洁架构中优雅使用事务
2024-11-18 19:26:04 +0800 CST
55个常用的JavaScript代码段
2024-11-18 22:38:45 +0800 CST
12个非常有用的JavaScript技巧
2024-11-19 05:36:14 +0800 CST
Vue3 实现页面上下滑动方案
2025-06-28 17:07:57 +0800 CST
120个实用CSS技巧汇总合集
2025-06-23 13:19:55 +0800 CST
程序员茄子在线接单