5月14日,Bun 发布了一条让前端圈炸锅的消息:核心运行时从 Zig 重写为 Rust。这个版本包含 6755 个提交,二进制文件体积缩小了 3-8 MB,各项性能基准测试在 macOS、Linux 和 Windows 上均达到或超越原有水平。
当初 Bun 以 Zig 起家,打出极致性能和极小体积的旗号,迅速在 Node.js 替代品的赛道上占据一席之地。如今却转身拥抱 Rust,这绝不是简单的语言偏好摇摆,而是一场关于工程质量和长期维护的战略豪赌。
抛弃 Zig:生态与招人的现实考量
Zig 曾是 Bun 的秘密武器。它没有 C 的历史包袱,能产出极小的二进制文件,且手动内存管理在底层运行时开发中有着天然的优势。但现实很骨感:Zig 的语言生态太小,编译器本身仍在剧烈迭代,偶尔还会出现破坏性的变更。更致命的是,懂 Zig 的资深工程师凤毛麟角。
Jarred Sumner 在公告中透露的决策逻辑非常务实:用 Rust 重写,不是因为 Zig 在性能上拖了后腿,而是因为招不到人、工具链不够稳、长期维护成本太高。Rust 有成熟的 Cargo 工具链,有庞大的社区,有现成的 crates.io 生态,这让工程协作和团队扩张变得可行。对于一个需要长期演进的复杂基础设施项目,语言的"招人难度"和"生态成熟度"往往比极致的编译体积更重要。
6755 个提交换来的硬指标
重写核心不是推倒重来那么简单,6755 个提交意味着几乎每一个底层模块都被重新审视和打磨。结果也令人意外:二进制体积反而缩小了 3-8 MB。
很多人直觉上认为 Rust 会比 Zig 产出更胖的二进制,因为 Rust 的标准库和冗余抽象更多。但 Bun 团队通过精细的 feature flag 控制、LTO(链接时优化)以及剥离不必要的标准库依赖,硬是把体积压了下来。性能方面,Rust 的零成本抽象和更成熟的 LLVM 优化后端发挥了关键作用,使得 Bun 在冷启动、热路径执行和内存占用上不仅没有退步,反而略有提升。
实战体验:体积与 IO 性能的直观对比
要感受这次重写带来的变化,最直接的方式就是看二进制体积和底层 IO 吞吐。你可以通过以下命令安装或升级到最新版 Bun,并运行一个简单的基准测试。
首先,安装并检查体积:
# 安装或升级到最新版 Bun
curl -fsSL https://bun.sh/install | bash
# 查看新版 Bun 的二进制体积
ls -lh ~/.bun/bin/bun
# 如果你保留有旧版二进制,可以直观对比 size 差异
接着,用一段 TypeScript 脚本测试 Bun 原生 API 的高并发文件读写能力,这正是底层运行时性能的硬指标:
// bench_io.ts - 测试 Bun 原生 IO 能力
const count = 5000;
const dir = `/tmp/bun-rust-bench`;
// 使用 Bun 原生 Shell 清理并创建目录
await Bun.$`rm -rf ${dir} && mkdir -p ${dir}`;
console.log(`并发写入 ${count} 个文件...`);
const writeStart = performance.now();
await Promise.all(
Array.from({ length: count }, (_, i) =>
Bun.write(`${dir}/file-${i}.txt`, `Powered by Rust ${i}`)
)
);
console.log(`写入耗时: ${(performance.now() - writeStart).toFixed(2)} ms`);
console.log(`并发读取 ${count} 个文件...`);
const readStart = performance.now();
await Promise.all(
Array.from({ length: count }, (_, i) =>
Bun.file(`${dir}/file-${i}.txt`).text()
)
);
console.log(`读取耗时: ${(performance.now() - readStart).toFixed(2)} ms`);
运行测试:
bun run bench_io.ts
你可以将这段脚本在旧版 Zig 驱动的 Bun 和新版 Rust 驱动的 Bun 上分别跑一遍,观察耗时和内存占用的差异。在大多数现代机器上,你会发现新版在大量小文件并发 IO 场景下表现更加稳定。
豪赌背后的风险与边界
Rust 并非银弹,这次重写也伴随着不容忽视的代价。
6755 个提交意味着漫长的开发分支和巨大的合并冲突期,这期间 Bun 的功能迭代几乎停滞,社区反馈的底层 Bug 修复也被延后。Rust 的编译速度远慢于 Zig,这会拖慢日常开发迭代和 CI 流水线。此外,虽然 Rust 的内存安全由编译器保证,但在 FFI 边界(Bun 仍需与 C/C++ 编写的 V8 和 JavaScriptCore 交互)和异步运行时的生命周期管理上,依然存在复杂的坑。
对于使用者而言,短期内如果遇到底层相关的崩溃,排查难度可能增加——因为底层逻辑的语言变了,堆栈信息的阅读习惯也要从 Zig trace 切换到 Rust panic backtrace。
采纳建议与升级清单
如果你正在生产环境中使用 Bun,这次重写带来的体积缩小和性能提升是实打实的收益,升级是值得的。但在升级前,请务必按以下清单排查:
- 跑通现有测试:底层运行时语言替换可能影响边缘场景(如特定 Buffer 操作、Worker 线程通信),确保核心业务测试全绿。
- 验证部署体积:在 Docker 或边缘计算场景中,重新构建镜像,确认二进制体积确实缩小,部署流水线未受影响。
- 关注错误堆栈:遇到底层崩溃时,注意阅读 Rust panic 信息,必要时使用
RUST_BACKTRACE=1环境变量获取完整调用栈。 - 评估原生模块兼容性:如果你有依赖 Bun 原生 FFI 的本地库,需验证其在新版运行时下的加载和调用是否正常。
Bun 的这次转身,证明了在基础设施软件的演进中,"能跑"只是起点,"能招到人持续维护"才是决定项目寿命的关键变量。Rust 赢得的不仅是性能,更是工程上的确定性。