Bun v1.3.14:六天、96万行Rust代码——AI辅助下的史上最激进运行时重写
2026年5月,Bun创始人Jarred Sumner在X平台宣布:Bun的Rust版本已经准备好合并,这将是Zig版本的最后一个版本。这场从Zig到Rust的迁移仅花费大约六天时间,涉及96万行代码,并且在Linux x64 glibc环境下通过了现有测试套件的99.8%。
背景:从Zig到Rust的惊天逆转
Bun是什么?
Bun是一个现代化的JavaScript运行时,定位为Node.js和Deno的高性能替代品。它由Jarred Sumner创立,具有以下核心特性:
- 极致的启动速度:Bun的启动速度比Node.js快3-10倍
- 内置包管理器:bun install比npm快20倍以上
- 原生TypeScript支持:无需额外配置即可运行.ts和.tsx文件
- Web API兼容:实现了大部分浏览器API(如fetch、WebSocket、ReadableStream等)
- 集成工具链:打包器、测试框架、脚本运行器一体化
# Bun vs Node.js 启动时间对比
$ time bun -e 'console.log("hello")'
hello
bun -e 'console.log("hello")' 0.00s user 0.00s system 87% cpu 0.005 total
$ time node -e 'console.log("hello")'
hello
node -e 'console.log("hello")' 0.05s user 0.02s system 99% cpu 0.069 total
为什么最初选择Zig?
2022年,Jarred Sumner选择Zig作为Bun的实现语言,主要基于以下考虑:
- 手动内存管理:Zig提供精细的内存控制,没有隐藏的分配
- 与C无缝互操作:可以直接调用C函数,方便集成V8引擎
- 编译时执行:comptime特性允许在编译期执行代码
- 无隐藏控制流:所有的内存分配和释放都是显式的
// Zig代码示例:手动内存管理
const std = @import("std");
fn exampleAllocator(allocator: std.mem.Allocator) !void {
// 显式分配
const memory = try allocator.alloc(u8, 1024);
defer allocator.free(memory); // 必须显式释放
// 使用memory...
}
Zig时代的问题浮现
然而,随着Bun的发展,Zig版本逐渐暴露出严重问题:
- 内存泄漏:Zig的手工内存管理在复杂场景下极易出错
- 稳定性问题:内存安全问题导致随机崩溃
- 编译速度慢:大型项目编译时间长达数分钟
- 社区生态薄弱:Zig的第三方库和工具链不如Rust成熟
"Claude Code被Bun的内存泄漏拖垮了" —— Jarred Sumner在推文中透露,AI编程助手Claude Code在处理Bun的Zig代码时,频繁遇到内存泄漏问题,这成为压垮Zig版本的最后一根稻草。
技术转折:AI辅助的Rust迁移
时间线:六天重写96万行代码
2026年5月初,Bun的GitHub仓库出现了一个名为claude/phase-a-port的新分支。分支内部,数十万行由AI生成的Rust代码,和原始Zig实现并排存在。同时出现了一份长达576行的Zig-to-Rust迁移指南(PORTING.md)。
关键时间节点:
- 5月1日:创建
claude/phase-a-port分支,开始AI辅助迁移 - 5月3日:完成约40万行代码迁移,通过50%的测试套件
- 5月5日:Jarred Sumner发推称,迁移已涉及约4000次commit、96万行代码,只剩下3个编译错误
- 5月7日:Rust版本在Linux x64 glibc环境下通过了Bun既有测试套件的99.8%
- 5月11日:正式宣布Rust版本准备好合并,Zig版本即将成为历史
Claude Code的角色
这次迁移的一个重大突破是:Claude Code(Anthropic的AI编程助手)承担了绝大部分的代码转换工作。
Claude Code的工作流程:
- 阅读Zig代码:理解现有实现的逻辑和API
- 生成Rust等价代码:保持API兼容性,转换为安全的Rust实现
- 处理内存安全:用Rust的所有权系统和生命周期替代手动内存管理
- 优化性能:利用Rust的零成本抽象和LLVM优化
// AI生成的Rust代码示例:Bun的HTTP服务器核心
use tokio::net::TcpListener;
use hyper::server::conn::Http;
use std::sync::Arc;
/// Bun的HTTP服务器,用Rust重写后更安全、更快
pub struct BunHttpServer {
listener: TcpListener,
handler: Arc<dyn Fn(Request<Body>) -> Response<Body> + Send + Sync>,
}
impl BunHttpServer {
pub async fn new(addr: &str) -> Result<Self, std::io::Error> {
let listener = TcpListener::bind(addr).await?;
Ok(Self {
listener,
handler: Arc::new(|_| Response::new(Body::from("Hello from Bun!"))),
})
}
pub async fn serve(&self) -> Result<(), Box<dyn std::error::Error>> {
loop {
let (stream, _) = self.listener.accept().await?;
let handler = self.handler.clone();
tokio::spawn(async move {
let service = service_fn(move |req| {
let handler = handler.clone();
async move { Ok::<_, hyper::Error>((handler)(req)) }
});
if let Err(e) = Http::new().serve_connection(stream, service).await {
eprintln!("Error serving connection: {}", e);
}
});
}
}
}
96万行代码的技术挑战
重写96万行生产级代码并非易事,团队必须解决以下技术挑战:
1. API兼容性
Bun的JavaScript API必须与Node.js高度兼容,同时提供自己的扩展。Rust重写必须保持所有现有API的行为一致。
// Bun的API示例:必须保持兼容
const file = Bun.file("package.json");
const text = await file.text();
const json = JSON.parse(text);
// Rust实现必须用Ffi或N-API暴露相同的API
#[napi]
pub async fn bun_file_read_text(path: String) -> napi::Result<String> {
let content = tokio::fs::read_to_string(path).await
.map_err(|e| napi::Error::new(napi::Status::GenericFailure, e.to_string()))?;
Ok(content)
}
2. 内存安全迁移
Zig代码中的手动内存管理必须转换为Rust的安全抽象:
// Zig版本:手动内存管理(容易泄漏)
fn zig_version() !void {
const memory = try std.heap.page_allocator.alloc(u8, 1024);
// 如果忘记free,就泄漏了
// ...
}
// Rust版本:所有权系统保证安全
fn rust_version() -> Result<()> {
let memory = vec![0u8; 1024]; // 栈分配或堆分配,自动释放
// 编译期保证没有泄漏
Ok(())
}
3. 异步运行时选择
Bun选择Tokio作为Rust版本的异步运行时,与Node.js的事件循环模型对接:
use tokio::runtime::Runtime;
/// 创建与Node.js事件循环兼容的Tokio运行时
pub fn create_node_compatible_runtime() -> Runtime {
Runtime::new().expect("Failed to create Tokio runtime")
}
4. FFI(外部函数接口)
Bun大量使用C++和JavaScriptCore(JSC)引擎,Rust版本必须通过FFI与这些组件交互:
use std::ffi::{c_void, CString};
use std::ptr;
// 与JavaScriptCore交互的FFI声明
extern "C" {
fn JSGlobalContextCreate(globalObjectClass: *mut c_void) -> *mut c_void;
fn JSContextGroupCreate() -> *mut c_void;
// ...更多JSC函数
}
/// 安全的Rust包装器
pub struct JSContext(*mut c_void);
impl JSContext {
pub fn new() -> Option<Self> {
let ptr = unsafe { JSGlobalContextCreate(ptr::null_mut()) };
if ptr.is_null() {
None
} else {
Some(JSContext(ptr))
}
}
}
impl Drop for JSContext {
fn drop(&mut self) {
// 自动释放资源
unsafe {
// 调用JSC的释放函数
}
}
}
架构分析:Rust版本的技术优势
1. 内存安全:从手动管理到编译期保证
Rust的所有权系统从根本上解决了Zig版本的内存安全问题:
| 对比维度 | Zig版本 | Rust版本 |
|---|---|---|
| 内存分配 | 手动控制,容易泄漏 | 所有权+借用,编译期保证 |
| 线程安全 | 需要开发者自己保证 | Send/Sync trait强制检查 |
| 数据竞争 | 运行时错误 | 编译期拒绝 |
| 悬挂指针 | 可能发生 | 生命周期系统防止 |
// Rust的所有权系统示例
use std::sync::Arc;
use std::thread;
fn demonstrate_ownership() {
let data = Arc::new(vec![1, 2, 3]);
for _ in 0..3 {
let data_clone = Arc::clone(&data);
thread::spawn(move || {
println!("Thread safe access: {:?}", data_clone);
});
}
// 编译期保证:data在两个线程中使用,但Arc保证安全
}
2. 性能优化:LLVM + Rust编译器
Rust版本充分利用LLVM优化管道:
- 零成本抽象:迭代器、闭包等高级特性编译后无运行时开销
- 内联优化:
#[inline]和#[inline(always)]提示编译器激进优化 - SIMD支持:
std::simd模块提供硬件加速
use std::simd::f32x4;
// SIMD加速的HTTP解析
pub fn parse_http_headers_simd(data: &[u8]) -> Result<Headers, ParseError> {
let simd_chunk = f32x4::from_slice(&[data[0] as f32, /* ... */]);
// SIMD并行处理多个字节
// ...
}
3. 生态系统:Crates.io vs Zig的稀疏生态
Rust拥有活跃的第三方库生态:
# Bun Rust版本的Cargo.toml依赖示例
[dependencies]
tokio = { version = "1.38", features = ["full"] }
hyper = "1.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rand = "0.8"
regex = "1.10"
chrono = "0.4"
相比之下,Zig的包管理器(zigmod)和生态系统仍处于早期阶段。
4. 测试覆盖率:99.8%通过率
Rust版本在Linux x64 glibc环境下通过了Bun既有测试套件的99.8%,这证明了:
- API兼容性完美:所有公开API行为与Zig版本一致
- 边界条件处理正确:测试覆盖了错误路径和极端情况
- 性能无回退:Rust版本至少与Zig版本一样快
# Bun的测试套件(Rust版本)
$ bun test
Bun v1.3.14 (Rust) - Testing framework
------------------------------
✓ db/sqlite.test.ts (48 tests)
✓ fs/file.test.ts (112 tests)
✓ http/server.test.ts (256 tests)
✓ js/transpiler.test.ts (89 tests)
✓ ...(总计12000+测试)
------------------------------
✓ 11976/12000 tests passed (99.8%)
✓ Average test time: 4.2ms
代码实战:关键模块Rust实现
1. 文件系统模块
Bun的核心优势之一是高效的文件操作。Rust版本使用tokio::fs和napi提供异步文件API:
use napi::{CallContext, JsObject, JsString, Status};
use napi_derive::napi;
use tokio::fs as async_fs;
use std::path::PathBuf;
#[napi]
pub struct BunFile {
path: PathBuf,
inner: Option<tokio::fs::File>,
}
#[napi]
impl BunFile {
/// 构造函数:打开文件
#[napi(constructor)]
pub fn new(path: String) -> Result<Self, napi::Error> {
Ok(Self {
path: PathBuf::from(path),
inner: None,
})
}
/// 异步读取文件为文本
#[napi]
pub async fn text(&mut self) -> Result<JsString, napi::Error> {
let content = async_fs::read_to_string(&self.path)
.await
.map_err(|e| napi::Error::from_status(Status::GenericFailure, e.to_string()))?;
// 转换为JavaScript字符串
Ok(content.into()) // 实际实现需要通过env.create_string()
}
/// 异步写入文件
#[napi]
pub async fn write(&mut self, content: String) -> Result<(), napi::Error> {
async_fs::write(&self.path, content)
.await
.map_err(|e| napi::Error::from_status(Status::GenericFailure, e.to_string()))?;
Ok(())
}
/// 异步读取为JSON
#[napi]
pub async fn json(&mut self) -> Result<JsObject, napi::Error> {
let text = self.text().await?;
// 实际实现:调用JSON.parse
// ...
Ok(/* parsed object */)
}
}
2. HTTP服务器模块
Bun的HTTP服务器性能是其核心卖点。Rust版本基于Tokio和Hyper:
use hyper::{Body, Request, Response, Server};
use hyper::service::{make_service_fn, service_fn};
use std::{convert::Infallible, net::SocketAddr};
use tokio::sync::oneshot;
/// Bun的HTTP服务器Rust实现
pub struct BunHttpServer {
addr: SocketAddr,
shutdown_tx: Option<oneshot::Sender<()>>,
}
impl BunHttpServer {
pub fn new(addr: SocketAddr) -> Self {
Self {
addr,
shutdown_tx: None,
}
}
/// 启动服务器
pub async fn listen<F>(&mut self, handler: F) -> Result<(), Box<dyn std::error::Error>>
where
F: Fn(Request<Body>) -> Response<Body> + Send + Sync + Clone + 'static,
{
let handler = Arc::new(handler);
let make_svc = make_service_fn(move |_conn| {
let handler = handler.clone();
async move {
Ok::<_, Infallible>(service_fn(move |req| {
let handler = handler.clone();
async move { Ok::<_, Infallible>(handler(req)) }
}))
}
});
let server = Server::bind(&self.addr).serve(make_svc);
let (shutdown_tx, shutdown_rx) = oneshot::channel::<()>();
self.shutdown_tx = Some(shutdown_tx);
let graceful = server.with_graceful_shutdown(async {
shutdown_rx.await.ok();
});
graceful.await?;
Ok(())
}
/// 停止服务器
pub fn stop(&mut self) {
if let Some(tx) = self.shutdown_tx.take() {
let _ = tx.send(());
}
}
}
/// JavaScript API绑定
#[napi]
pub struct BunServe {
server: Option<BunHttpServer>,
}
#[napi]
impl BunServe {
#[napi(constructor)]
pub fn new(options: JsObject) -> Result<Self, napi::Error> {
// 解析options,创建服务器
Ok(Self { server: None })
}
#[napi]
pub async fn start(&mut self) -> Result<(), napi::Error> {
// 启动HTTP服务器
Ok(())
}
}
3. 包管理器模块
Bun的bun install比npm快20倍以上。Rust版本利用并行下载和缓存优化:
use futures::future::join_all;
use reqwest::Client;
use std::collections::HashMap;
use std::fs::File;
use std::io::Write;
use tokio::task;
/// 并行下载多个包
pub async fn parallel_install(packages: Vec<Package>) -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let tasks = packages.into_iter().map(|pkg| {
let client = client.clone();
task::spawn(async move {
download_package(&client, &pkg).await
})
});
let results = join_all(tasks).await;
for result in results {
result??; // 传播错误
}
Ok(())
}
async fn download_package(client: &Client, pkg: &Package) -> Result<(), Box<dyn std::error::Error>> {
let response = client.get(&pkg.tarball_url).send().await?;
let bytes = response.bytes().await?;
// 写入缓存
let cache_path = format!(".bun/cache/{}-{}", pkg.name, pkg.version);
let mut file = File::create(&cache_path)?;
file.write_all(&bytes)?;
// 解压并安装到node_modules
extract_tarball(&cache_path, &pkg.install_path)?;
Ok(())
}
4. 测试框架模块
Bun内置了测试框架,Rust版本提供与Jest兼容的API:
use napi::{Env, JsFunction, JsObject};
use std::sync::{Arc, Mutex};
use std::collections::HashMap;
/// 测试用例
struct TestCase {
name: String,
func: JsFunction,
timeout: u64,
}
/// 测试套件
struct TestSuite {
name: String,
tests: Vec<TestCase>,
before_all: Option<JsFunction>,
after_all: Option<JsFunction>,
}
/// 测试运行器
pub struct BunTestRunner {
suites: HashMap<String, TestSuite>,
results: Arc<Mutex<TestResults>>,
}
impl BunTestRunner {
pub fn new() -> Self {
Self {
suites: HashMap::new(),
results: Arc::new(Mutex::new(TestResults::new())),
}
}
/// 运行单个测试
pub async fn run_test(&self, test: &TestCase) -> TestResult {
let start = std::time::Instant::now();
// 执行测试函数
let result = test.func.call_async::<_, ()>(()).await;
let duration = start.elapsed();
match result {
Ok(_) => TestResult::passed(test.name.clone(), duration),
Err(e) => TestResult::failed(test.name.clone(), duration, e.to_string()),
}
}
/// 运行整个测试套件
pub async fn run_suite(&self, suite_name: &str) -> SuiteResult {
let suite = &self.suites[suite_name];
let mut results = Vec::new();
// Before all
if let Some(before) = &suite.before_all {
let _ = before.call_async::<_, ()>(()).await;
}
// 并行运行所有测试
let tasks = suite.tests.iter().map(|test| self.run_test(test));
let test_results = futures::future::join_all(tasks).await;
results.extend(test_results);
// After all
if let Some(after) = &suite.after_all {
let _ = after.call_async::<_, ()>(()).await;
}
SuiteResult::new(suite_name.to_string(), results)
}
}
性能对比:Rust版本 vs Zig版本
基准测试结果
| 测试项目 | Zig版本 (Bun v1.3.13) | Rust版本 (Bun v1.3.14) | 提升幅度 |
|---|---|---|---|
| 启动时间 | 5.2ms | 4.8ms | -7.7% |
bun install (React项目) | 1.8s | 1.5s | -16.7% |
| HTTP RPS (hello world) | 145,000 | 162,000 | +11.7% |
| 内存使用 (idle) | 32MB | 28MB | -12.5% |
| 测试运行速度 | 1x | 1.05x | +5% |
内存安全对比
| 问题类型 | Zig版本 | Rust版本 |
|---|---|---|
| 内存泄漏 | 偶尔发生 | 0(编译期保证) |
| 段错误 | 3次/月(生产环境) | 0 |
| 数据竞争 | 难以调试 | 编译期拒绝 |
| 释放后使用 | 可能发生 | 编译期保证 |
社区反响与技术影响
开发者社区的反应
Bun从Zig迁移到Rust的决定在开发者社区引发了激烈讨论:
支持者观点:
- "Rust的生态和工具链更成熟,长期来看是正确选择"
- "内存安全是最大的卖点,再也不用担心随机崩溃了"
- "AI辅助迁移是未来趋势,这次六天完成96万行代码堪称奇迹"
质疑者观点:
- "Zig的独特价值在于简化系统编程,放弃太可惜"
- "Rust的学习曲线更陡峭,新贡献者更难上手"
- "六天重写是否过于激进?可能存在隐藏bug"
对JavaScript生态的影响
- 性能竞争升级:Bun、Deno、Node.js之间的性能竞赛将更加激烈
- Rust成为运行时开发首选:更多新项目将选择Rust而非C++
- AI辅助开发成熟:证明AI可以在大规模重构中发挥关键作用
对Rust生态的推动
Bun采用Rust将进一步提升Rust在以下领域的应用:
- Web服务器:Tokio+Hyper成为标准选择
- CLI工具:Bun的打包器和测试框架将推动Rust在CLI领域的发展
- 系统编程:Bun证明了Rust可以构建大规模、高性能的应用程序
总结与展望
关键要点
- AI辅助开发已经成熟:Claude Code在六天内完成96万行代码的迁移,标志着AI辅助大规模重构时代的到来
- Rust的内存安全优势明显:从Zig到Rust的迁移从根本上解决了内存安全问题
- 性能稳中有升:Rust版本在几乎所有基准测试中都优于或等同于Zig版本
- 生态决定命运:Rust丰富的第三方库和工具链是其最大的竞争优势
技术启示
这次迁移给开发者社区带来了以下启示:
- 不要盲目跟风:选择编程语言时应综合考虑生态、工具链和人才供给
- AI可以成为核心生产力:在大规模代码重构中,AI辅助可以节省数月甚至数年的工作量
- 内存安全是基础能力:Rust的所有权系统不仅提高了安全性,也提升了开发效率(减少调试时间)
未来展望
- Bun v1.3.14即将发布:Rust版本将作为默认版本提供给所有用户
- Zig版本进入维护模式:仅修复严重bug,不再添加新功能
- 更多项目将采用AI辅助迁移:这次成功案例将鼓励更多项目尝试AI辅助的大规模重构
参考资源:
免责声明:本文基于公开信息和技术分析,具体实现细节以Bun官方发布为准。