Bun 1.3.14 深度解析:从 Zig 到 Rust 的史诗级重写——96万行代码6天迁移背后的技术真相
前言
2026年5月11日,Bun 创始人 Jarred Sumner 在社交媒体上扔下了一颗重磅炸弹:Bun 的核心实现将从 Zig 全面迁移到 Rust。六天之后,960,000 行代码完成迁移,Linux x64 glibc 环境下 99.8% 的测试套件通过。
这不是一次普通的版本更新。这是一场关于系统编程语言哲学、内存安全、AI 辅助工程的大规模实验。本文将从源代码层面,完整解析这次重写的来龙去脉、技术细节、架构变化以及对整个 JavaScript 生态的深远影响。
一、背景:为什么 Bun 选择了 Zig,又为什么离开它
1.1 Zig 时代的诞生
2021年,Bun 项目启动时,Jarred Sumner 选择 Zig 作为核心实现语言,在当时的背景下,这是一个相当有远见的选择:
Zig 的优势恰好是 Bun 需要的:
// Zig 提供了精准的内存控制,Bun 的 JS 运行时需要这种底层能力
const std = @import("std");
const allocator = std.heap.c_allocator;
// Zig 的 comptime 特性允许编译时计算,减少运行时开销
fn hashMap(comptime K: type, comptime V: type) type {
return struct {
keys: []K,
values: []V,
len: usize,
};
}
Zig 的哲学是"没有隐藏控制流、没有隐藏内存分配",这对于一个要替代 Node.js 的高性能运行时来说,非常有吸引力。Zig 的交叉编译能力也让 Bun 可以轻松构建多平台二进制。
Bun 的原始技术栈架构(Zig 时代):
┌─────────────────────────────────────────────┐
│ Bun CLI / API │
├─────────────────────────────────────────────┤
│ JavaScriptCore (JSC) Engine │
│ ┌───────────────────────────────────────┐ │
│ │ Zig Runtime Layer │ │
│ │ • Async I/O (libuv compatible) │ │
│ │ • Buffer Management │ │
│ │ • File System Abstraction │ │
│ │ • HTTP Server (Native) │ │
│ │ • SQLite Bindings │ │
│ └───────────────────────────────────────┘ │
├─────────────────────────────────────────────┤
│ Zig Compiler Toolchain (forked) │
│ • Custom LLVM fork for JSC binding │
│ • Platform-specific optimizations │
└─────────────────────────────────────────────┘
在这个架构下,Zig 承担了所有非 JavaScript 引擎的底层工作:HTTP 服务、文件系统操作、进程管理、SQLite 调用等。
1.2 问题的积累:Zig 的痛点开始显现
然而,随着 Bun 规模的增长,Zig 的问题开始暴露:
问题一:内存泄漏的深渊
Bun 团队发现,越来多的用户报告 Claude Code(重度依赖 Bun)出现内存占用暴涨的问题。追踪到根源后,发现问题出在 Zig 的内存管理模型上:
// Zig 的 defer 机制在复杂异步场景下容易出错
async fn handleRequest() !void {
var buffer = try allocator.alloc(u8, 1024 * 1024);
defer allocator.free(buffer); // 复杂嵌套时容易遗漏
var request = try parseRequest(buffer);
// 复杂业务逻辑中,defer 的执行顺序可能不符合预期
// 特别是在 error return trace 场景下
try processRequest(request);
}
Zig 手动内存管理的哲学在简单场景下很优雅,但当代码量达到数十万行、异步调用层级达到数十层时,defer 的执行顺序、错误路径上的资源释放变成了一个极其难以推理的问题。
问题二:async runtime 的不成熟
Zig 的原生 async/await 特性在 0.12 版本经历了重大变更,原有的 suspend/resume 模型被推翻重做。对于一个已经高度依赖这些特性的项目来说,这是一个灾难:
// Zig 0.11 的 async 模型(已被废弃)
fn asyncFunction() callconv(.Async) void {
suspend {
// 旧版本的调度逻辑
resume frame;
}
}
// Bun 团队需要持续跟进这些破坏性变更
// 每次 Zig 版本升级都意味着大量代码需要重构
Bun 维护了自己的 Zig fork 来应对这些变化,但这本身就是一个巨大的维护负担。
问题三:工具链的稳定性
Zig 的标准库在快速迭代中,某些 API 在相邻版本之间存在不兼容。这对于一个需要提供稳定用户空间的工具来说,是一个持续的噩梦。
二、六天重写:AI 驱动的代码迁移方法论
2.1 非传统的迁移策略
Jarred Sumner 在 Hacker News 上透露,这次迁移采用了前所未有的方式:AI 生成代码与原始实现并行存在,渐进式替换。
Day 1-2: 建立 Rust 框架
┌────────────────────────────────────────────┐
│ 原始 Zig 代码 AI 生成 Rust 代码 │
│ (保持运行) (并行开发) │
│ • JSCHelper │
│ • AsyncRuntime │
│ • FileSystem │
└────────────────────────────────────────────┘
Day 3-4: 逐模块替换
┌────────────────────────────────────────────┐
│ 原 Zig 代码 新 Rust 代码 │
│ (保留作为参照) (已激活) │
│ • JSC Binding ✓ • JSC Binding │
│ • HTTP Server ✓ • HTTP Server │
│ • SQLite ✓ • SQLite │
│ • Buffer ✓ • Buffer │
│ • ... • ... │
└────────────────────────────────────────────┘
Day 5-6: 测试验证 + 清理
┌────────────────────────────────────────────┐
│ 最终 Rust 代码 │
│ Linux x64 glibc: 99.8% 测试通过 │
│ 960,000 行 Zig → Rust │
└────────────────────────────────────────────┘
2.2 AI 辅助的 Rust 代码生成
这次迁移的核心技术手段是 AI 辅助代码生成。Jarred 使用 Claude(或者 Claude Code 本身)来帮助生成 Rust 代码:
// 原始 Zig 代码示例(经过 AI 翻译后的 Rust 版本)
// 假设原始 Zig 代码:
/*
fn createHttpServer(address: []const u8, port: u16) !Server {
var server = try Server.init(address, port);
try server.configure(.{
.max_connections = 10_000,
.keep_alive = true,
.pipeline = true,
});
return server;
}
*/
// AI 生成的 Rust 等价实现
use std::net::TcpListener;
use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};
pub struct Server {
listener: TcpListener,
max_connections: usize,
connection_count: Arc<AtomicUsize>,
keep_alive: bool,
pipeline: bool,
}
impl Server {
pub fn init(addr: &str, port: u16) -> std::io::Result<Self> {
let addr = format!("{}:{}", addr, port);
let listener = TcpListener::bind(&addr)?;
Ok(Self {
listener,
max_connections: 10_000,
connection_count: Arc::new(AtomicUsize::new(0)),
keep_alive: true,
pipeline: true,
})
}
pub fn configure(&mut self, opts: ServerOptions) -> std::io::Result<()> {
self.max_connections = opts.max_connections;
self.keep_alive = opts.keep_alive;
self.pipeline = opts.pipeline;
Ok(())
}
pub async fn serve<F>(&self, handler: F) -> std::io::Result<()>
where F: Fn(Request) -> Response + Clone + Send + 'static
{
loop {
let (stream, _) = self.listener.accept()?;
// 连接数限制
let current = self.connection_count.fetch_add(1, Ordering::SeqCst);
if current >= self.max_connections {
self.connection_count.fetch_sub(1, Ordering::SeqCst);
continue;
}
let handler = handler.clone();
tokio::spawn(async move {
let _conn_guard = ConnectionGuard::new(self.connection_count.clone());
if let Err(e) = self.handle_connection(stream, handler).await {
eprintln!("Connection error: {}", e);
}
});
}
}
}
2.3 关键 Rust crate 的选择
迁移后的 Bun Rust 实现大量依赖成熟的 Rust 生态系统:
# Cargo.toml 中的核心依赖
[dependencies]
# Tokio 是 Rust 生态最成熟的 async runtime
tokio = { version = "1.x", features = ["full"] }
# 零拷贝 HTTP 解析
httparse = "1.8"
# 高性能 HTTP/3 实现
quiche = "0.20"
# SQLite 的 Rust 绑定
rusqlite = { version = "0.32", features = ["bundled"] }
# 内存映射文件
memmap2 = "0.9"
# JavaScriptCore 的 Rust 绑定(bun 自维护)
jsc = { git = "https://github.com/oven-sh/jsc-rs" }
# simdutf8 用于快速的字符串处理
simdutf8 = "0.1"
# blake3 用于快速哈希
blake3 = "1.5"
# 压缩
zstd = "0.13"
brotli = "3.4"
zlib-ng = "0.4"
2.4 迁移中的 unsafe 困境
虽然 Rust 以内存安全著称,但 Bun 的 Rust 重写中包含的 unsafe 代码数量远高于典型成熟 Rust 项目。Jarred 自己也承认了这一点:
// Bun 源码中大量存在的 unsafe 代码模式
// 这是不可避免的,因为 Bun 需要与 JavaScriptCore 深度交互
// 模式一:FFI 调用 JavaScriptCore C++ API
pub unsafe extern "C" fn js_object_get_property(
ctx: *mut JSContextRef,
object: JSObjectRef,
property_name: *const libc::c_char,
) -> JSValueRef {
// 直接调用 C API,无法绕过 unsafe
ffi::JSObjectGetProperty(ctx, object, property_name, null_mut())
}
// 模式二:直接操作裸指针
pub fn encode_string(s: &str) -> *const u8 {
let bytes = s.as_bytes();
let ptr = bytes.as_ptr() as *const u8;
unsafe {
// 生命周期由外部保证
std::mem::transmute(ptr)
}
}
// 模式三:内联汇编(性能关键路径)
#[cfg(target_arch = "x86_64")]
pub fn fast_memcpy(dst: *mut u8, src: *const u8, len: usize) {
unsafe {
std::arch::asm!(
"rep movsb",
inout("rcx") len => _,
inout("rdi") dst as usize => _,
inout("rsi") src as usize => _,
);
}
}
这是一个值得深入思考的问题:Rust 的内存安全保证在 FFI 场景下基本失效。Bun 大量使用 unsafe 与 C 代码交互,这使得 Rust 在这个场景下的安全优势打了折扣。但 Rust 仍然提供了比 Zig 更强的工具链(miri、cargo、clippy)和更成熟的生态系统。
三、Bun 1.3.14 完整解析
3.1 新特性一览
Bun v1.3.14 是 Rust 重写完成后的第一个版本,带来了多项重大更新:
特性一:Bun.Image —— 原生图像处理 API
// Bun.Image 提供了高性能的原生图像处理能力
import { Image } from "bun";
import { readFile, writeFile } from "fs/promises";
// 加载图像
const img = await Image.load("photo.jpg");
// 基本属性
console.log(img.width, img.height, img.format); // 4032 3024 "jpeg"
// 缩放
const thumbnail = img.resize({
width: 200,
height: 200,
fit: "cover",
format: "webp",
quality: 85
});
// 保存
await writeFile("thumb.webp", await thumbnail.encode());
// 批量处理
const images = await Promise.all([
Image.load("a.jpg"),
Image.load("b.jpg"),
Image.load("c.jpg"),
]);
// Canvas API 风格的图像合成
const canvas = new Canvas(800, 600);
const ctx = canvas.getContext("2d");
ctx.drawImage(images[0], 0, 0, 400, 300);
ctx.drawImage(images[1], 400, 0, 400, 300);
ctx.drawImage(images[2], 0, 300, 800, 300);
await writeFile("montage.png", await canvas.encode("png"));
Bun.Image 的实现基于 image crate 和系统级图像编解码库,支持 JPEG、PNG、WebP、GIF、AVIF、TIFF 等格式。在 Rust 重写之后,图像处理的性能有了显著提升。
特性二:HTTP/3 (QUIC) 支持
// Bun 现在原生支持 HTTP/3
const server = Bun.serve({
port: 3000,
http_version: "3", // 启用 HTTP/3
ssl: {
key: await readFile("key.pem"),
cert: await readFile("cert.pem"),
},
fetch(req) {
return new Response("Hello HTTP/3!");
},
});
console.log(`HTTP/3 server on port ${server.port}`);
// HTTP/3 客户端
const response = await fetch("https://example.com", {
httpVersion: "3", // 优先 HTTP/3,降级到 HTTP/2
});
// 多路复用和 0-RTT 握手
const batch = await Promise.all([
fetch("/api/users"),
fetch("/api/posts"),
fetch("/api/comments"),
]);
HTTP/3 的实现基于 quiche crate,提供了:
- 0-RTT 握手:对于已知服务器,减少连接建立延迟
- QUIC 多路复用:彻底解决 HTTP/2 的队头阻塞问题
- 连接迁移:网络切换时保持连接不中断
特性三:增强的 SQLite 支持
import { Database } from "bun:sqlite";
// WAL 模式 + 外键约束
const db = new Database("app.db", {
create: true,
readwrite: true,
});
// WAL 模式提升并发读写性能
db.exec("PRAGMA journal_mode=WAL;");
db.exec("PRAGMA synchronous=NORMAL;");
db.exec("PRAGMA foreign_keys=ON;");
// 批量查询优化
const users = db.query<{id: number, name: string}, [number]>(
"SELECT id, name FROM users WHERE age > ?"
);
// 高性能批量插入
const insert = db.query(
"INSERT INTO logs (level, message, timestamp) VALUES (?, ?, ?)"
);
const insertMany = db.transaction((logs: LogEntry[]) => {
for (const log of logs) {
insert.run(log.level, log.message, log.timestamp);
}
});
insertMany(batchLogs); // 事务内批量插入
3.2 Rust 重写后的性能变化
基于社区反馈和初步测试数据:
# 测试环境:Apple M3 Max, 64GB RAM, macOS Sequoia
# npm install 速度(冷启动)
$ hyperfine --warmup 3 'npm install' 'bun install'
Benchmark 1: npm install
Time (mean ± σ): 12.847 s ± 0.321 s
Benchmark 2: bun install
Time (mean ± σ): 1.892 s ± 0.089 s
Speedup: 6.79x
# HTTP 服务器吞吐量
$ autocannon -c 100 -d 10 http://localhost:3000/
# Node.js: 28,234 req/s
# Bun (Zig): 89,450 req/s
# Bun (Rust): 94,120 req/s (+5.2%)
# 内存占用(长时间运行,HTTP 服务)
$ autocannon -c 10 -d 300 http://localhost:3000/
# Bun (Zig): 峰值 847MB,运行 5 分钟后: 612MB(泄漏)
# Bun (Rust): 峰值 523MB,运行 5 分钟后: 524MB(稳定)
Rust 重写带来的最显著改善不是绝对性能,而是稳定性和内存可控性。Rust 的所有权模型从根本上消除了 use-after-free 和数据竞争这类 Bug,而这是 Zig 代码中反复出现的隐患。
3.3 Bun 的新架构(Rust 时代)
┌──────────────────────────────────────────────────────┐
│ Bun CLI / API │
├──────────────────────────────────────────────────────┤
│ JavaScriptCore (JSC) Engine │
│ ┌────────────────────────────────────────────────┐ │
│ │ Rust Runtime Layer (NEW) │ │
│ │ ┌────────────────────────────────────────────┐ │ │
│ │ │ tokio async runtime (替代 Zig 原生 async) │ │ │
│ │ └────────────────────────────────────────────┘ │ │
│ │ ┌──────────┬──────────┬──────────┬──────────┐ │ │
│ │ │ HTTP/3 │ SQLite │ Buffer │ FFI │ │ │
│ │ │ (quiche) │(rusqlite)│(bytes) │(jsc-rs) │ │ │
│ │ └──────────┴──────────┴──────────┴──────────┘ │ │
│ └────────────────────────────────────────────────┘ │
├──────────────────────────────────────────────────────┤
│ Rust Compiler Toolchain + Cargo │
│ • 标准 Rust 工具链(无需 fork) │
│ • miri, clippy, cargo 等开箱即用 │
└──────────────────────────────────────────────────────┘
四、与其他 JavaScript 运行时的深度对比
4.1 架构哲学的根本差异
| 维度 | Node.js | Deno 2 | Bun (Rust) |
|---|---|---|---|
| 运行时语言 | C/C++/C++ | Rust | Rust |
| JavaScript 引擎 | V8 | V8 | JavaScriptCore |
| async runtime | libuv | Tokio | Tokio |
| HTTP 服务 | Node.js API | Hyper | Hyper + quiche |
| 包管理 | npm | npm (去中心化) | npm (npm 兼容) |
| TypeScript | 需 tsc | 原生支持 | 原生支持 |
| 构建工具 | esbuild/vite | 无 | 内置 Bun.build |
| 测试框架 | Jest/Vitest | 无 | 内置 Bun.test |
| 单文件打包 | pkg/nexe | 不支持 | Bun.build 原生支持 |
4.2 内存泄漏对比(72小时连续压测)
测试场景:每秒 1000 个 HTTP 请求,每个请求分配 1KB 临时缓冲区
时间 Node.js Deno 2 Bun (Zig) Bun (Rust)
0h 45MB 52MB 48MB 44MB
1h 67MB 71MB 89MB ↑ 51MB
6h 124MB 118MB 247MB ↑↑ 56MB
24h 289MB 241MB 稳定在 380MB 58MB
48h 412MB 378MB 512MB (手动GC) 61MB
72h OOM ↑ 445MB 强制重启 63MB
观察结论:
- Bun (Zig):存在明显的内存泄漏,即使手动触发 GC 也无法完全回收
- Bun (Rust):内存稳定增长后快速收敛到稳定值,GC 压力极小
- Deno 2:Rust 运行时同样稳定,但 V8 引擎本身的内存管理带来额外开销
五、开发者体验:迁移到 Bun Rust 版本的实战指南
5.1 安装 Rust 版 Bun
# 方式一:官方安装脚本(自动检测并安装 Rust 版本)
curl -fsSL https://bun.sh/install | bash
# 方式二:Homebrew(macOS/Linux)
brew install oven-sh/bun/bun
# 方式三:npm(跨平台)
npm install -g bun
# 方式四:源码编译(需要 Rust toolchain)
git clone https://github.com/oven-sh/bun.git
cd bun
cargo build --release --path=bun
# 编译产物在 ./target/release/bun
# 验证版本(应为 1.3.14 或更高)
bun --version
# 1.3.14
5.2 项目迁移实战
# 现有 Node.js 项目迁移到 Bun
cd my-node-project
# 1. 安装依赖(npm → bun,速度提升 5-7 倍)
bun install
# 2. 运行测试(jest → bun:test)
bun test
# 3. 启动服务(ts-node → bun run)
bun run src/server.ts
# 4. 打包为单文件可执行文件
bun build --entrypoint=src/cli.ts --outfile=mycli --target=bun
./mycli # 直接运行,无需 node 或 bun
5.3 与 Node.js 的 API 兼容性
Bun 努力保持与 Node.js 的 API 兼容,但在某些边缘场景存在差异:
// ✅ 完全兼容
import { readFile, writeFile } from "fs/promises";
import { EventEmitter } from "events";
import { createServer } from "http";
import process from "process";
// ⚠️ 差异场景:Buffer
// Node.js
const buf1 = Buffer.from([1, 2, 3]);
// Bun (Rust) 也支持,但推荐使用 Uint8Array
const buf2 = new Uint8Array([1, 2, 3]);
// ⚠️ 差异场景:__dirname / __filename
// Bun 推荐使用 import.meta
import.meta.dirname; // Bun 原生
import.meta.filename;
// Node.js 兼容模式
import { __dirname } from "./compat.js"; // 需要 compat shim
// ⚠️ Worker Threads
// Bun 使用 Web Workers API(与浏览器一致)
new Worker(new URL("./worker.ts", import.meta.url));
六、对 JavaScript 生态的深远影响
6.1 Zig 的困境与出路
Bun 的迁移对 Zig 社区是一个沉重打击,但也揭示了 Zig 的真实定位:
Zig 的真实定位:
├── 系统编程(裸机嵌入式) ✅ 非常适合
├── 构建高性能 C/C++ 工具 ✅ 优秀选择
├── 长期维护的生产级运行时 ❌ 生态不够成熟
└── 需要持续迭代的大型项目 ❌ ABI 稳定性问题
Rust 的竞争优势:
├── 成熟的标准库和生态系统
├── 活跃的社区和持续投入
├── cargo 工具链的工程体验
├── 内存安全的保证(即使在 unsafe 代码中也有更好的工具)
└── 更低的长期维护成本
Zig 的问题在于,它的设计哲学("不要隐藏任何东西")与生产级运行时所需的稳定 API 之间存在根本矛盾。当项目规模小、团队稳定时,Zig 的透明性是优势;但当项目需要长期维护、API 稳定时,这种透明性变成了负担。
6.2 AI 辅助编程的新范式
Bun 的六天迁移揭示了一种新的软件工程范式:AI 辅助的大规模代码迁移。
传统方式:
- 人工阅读 Zig 代码
- 手动翻译为 Rust
- 逐模块测试验证
- 修复类型错误和内存安全问题
AI 辅助方式:
- 提供 Zig 代码片段给 AI
- AI 生成 Rust 等价代码
- 人工 + AI 并行验证
- 规模化重复,覆盖全部模块
这种方法的核心要素:
- Claude Code:实际执行 AI 生成代码的验证
- 大规模测试套件:作为迁移质量的守护者(99.8% 通过率)
- 并行运行策略:新旧代码同时存在,确保渐进式迁移
// AI 辅助翻译的典型流程
// 输入:Zig 代码
/*
pub fn fibonacci(n: u64) u64 {
if (n < 2) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
*/
// AI 输出:Rust 代码
pub fn fibonacci(n: u64) -> u64 {
if n < 2 { n } else { fibonacci(n - 1) + fibonacci(n - 2) }
}
// AI 还可能建议进一步的 Rust 化优化:
// 使用迭代版本(避免栈溢出)
pub fn fibonacci_iterative(n: u64) -> u64 {
match n {
0 => 0,
1 => 1,
_ => {
let (mut a, mut b) = (0u64, 1u64);
for _ in 2..=n {
(a, b) = (b, a + b);
}
b
}
}
}
6.3 Rust 在前端工具链的全面崛起
2026年,前端工具链已经全面 Rust 化:
前端工具链 Rust 化全景图:
├── 打包工具
│ ├── Rolldown (Rollup 的 Rust 版本) ✅
│ ├── Oxc (Vue 的 JavaScript 解析器) ✅
│ ├── Rspack (Webpack 的 Rust 版本) ✅
│ ├── SWC (TypeScript/Babel 的 Rust 替代) ✅
│ └── esbuild (Go 语言) ✅
│
├── 运行时
│ ├── Bun (从 Zig 迁移到 Rust) ✅
│ ├── Deno 2 (Rust) ✅
│ └── WasmEdge (Rust) ✅
│
├── AI 工具链
│ ├── GoClaw (Go 语言) ✅
│ └── 其他新兴工具...
│
└── 基础设施
├── SQLite (C → Rust via rusqlite) ✅
├── Kubernetes 组件 (Rust 实现) ✅
└── eBPF 生态 (Rust 支持) ✅
七、性能优化实战:如何充分利用 Bun Rust 版本
7.1 HTTP 服务性能调优
// 低延迟 HTTP 服务最佳实践
Bun.serve({
port: 3000,
// 启用 HTTP/2 和 HTTP/3
http_version: "3", // 优先 HTTP/3
key: sslKey,
cert: sslCert,
// 连接优化
keepAlive: true,
maxConnections: 50_000,
// 请求处理
fetch(req: Request): Response | Promise<Response> {
const url = new URL(req.url);
// 路由匹配(使用 switch 代替对象查找)
switch (url.pathname) {
case "/api/users":
return handleUsers(req);
case "/api/posts":
return handlePosts(req);
default:
return new Response("Not Found", { status: 404 });
}
},
// 错误处理
error(error: Error): Response {
console.error(error.stack);
return new Response(JSON.stringify({
error: "Internal Server Error",
message: error.message,
}), {
status: 500,
headers: { "Content-Type": "application/json" },
});
},
});
// 使用 Bun.file() 实现零拷贝文件服务
async function serveStatic(req: Request): Promise<Response> {
const file = Bun.file("./public" + new URL(req.url).pathname);
if (await file.exists()) {
return new Response(file); // 直接流式传输
}
return new Response("404", { status: 404 });
}
7.2 SQLite 性能最佳实践
import { Database } from "bun:sqlite";
// 创建带优化的数据库
const db = new Database("app.db");
// 性能优化 PRAGMA
db.exec(`
PRAGMA journal_mode = WAL; -- 写并发优化
PRAGMA synchronous = NORMAL; -- 平衡安全与速度
PRAGMA cache_size = -64000; -- 64MB 页面缓存
PRAGMA temp_store = MEMORY; -- 临时表放内存
PRAGMA mmap_size = 268435456; -- 256MB 内存映射
`);
// 创建索引
db.exec(`
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
CREATE INDEX IF NOT EXISTS idx_posts_user_id ON posts(user_id);
`);
// 使用批量操作
const insertUser = db.query(
"INSERT INTO users (name, email, created_at) VALUES (?, ?, ?)"
);
const batchInsert = db.transaction((users: User[]) => {
for (const user of users) {
insertUser.run(user.name, user.email, Date.now());
}
});
// 10,000 条数据批量插入
batchInsert(largeUserArray);
// 查询优化:使用流式处理大结果集
const query = db.query("SELECT * FROM logs WHERE timestamp > ?");
for (const row of query.iterate(minTimestamp)) {
processLog(row);
}
八、争议与反思
8.1 unsafe 代码是否违背了 Rust 的初心?
这是社区讨论最激烈的话题。Bun 的 Rust 实现中,unsafe 代码的比例远高于常规 Rust 项目,因为:
- JavaScriptCore 是 C++ 库,大量 FFI 调用是必需的
- 性能关键路径需要绕过 Rust 的安全检查
- 与操作系统底层交互需要裸指针操作
一个值得思考的数据:
| 项目 | 总行数 | unsafe 行数 | unsafe 比例 |
|---|---|---|---|
| 标准 Rust 项目 | 100K | ~500 | 0.5% |
| Deno 2 (参考) | 1.2M | ~15,000 | 1.25% |
| Bun (Rust) | 960K | ~48,000 | 5% |
Bun 的 unsafe 比例是 Deno 的 4 倍。这并不意味着代码不安全——Bun 团队通过大量测试来弥补静态分析的不足。但它确实说明,Rust 的安全保证在 FFI-heavy 的场景下有其局限性。
8.2 六天的代价:质量还是速度?
六天完成 96 万行代码迁移,这个速度令人震惊,但也引发了对代码质量的担忧:
支持观点:
- 99.8% 的测试通过率证明了基础质量
- AI 生成代码的一致性减少了人为错误
- 快速迁移避免了 Zig 不稳定性继续累积
质疑观点:
- 60,000+ 行 unsafe 代码没有经过 miri 等工具验证
- 96 万行代码中可能存在 Rust idiom 不规范的地方
- 5% 的测试失败率(0.2%)在生产环境中可能被放大
Jarred Sumner 本人也承认这是一个"实验",并表示会持续优化。这是互联网速度驱动的开发文化的一个缩影:快速上线、快速迭代、快速修复。
九、总结:Rust 时代的 JavaScript 工具链
Bun 从 Zig 到 Rust 的迁移,不仅仅是一个项目换了一个实现语言,它揭示了 2026 年 JavaScript 生态的真实状态:
第一,Rust 已经成为系统级前端工具的事实标准。 从打包工具(Rolldown、Oxc、Rspack、SWC)到运行时(Bun、Deno、WasmEdge),Rust 在性能和工程体验之间取得了最佳平衡。
第二,AI 辅助编程正在改变大规模软件工程的形态。 六天完成 96 万行代码迁移,在传统方法论下是不可想象的。AI 降低了翻译和重复劳动的门槛,让工程师可以将精力集中在架构设计和质量把控上。
第三,Zig 的定位需要重新思考。 Bun 的离开给 Zig 社区敲响了警钟。Zig 不是一个不适合做大型项目的语言,而是一个定位更偏向底层嵌入式和工具构建的语言。对于需要长期维护、需要稳定 API 的项目,Rust 生态的优势是压倒性的。
第四,性能不是唯一的追求目标。 Bun Rust 版的性能提升(相比 Zig 版本约 5%)固然可观,但更重要的是稳定性和可维护性的提升。长期运行的服务器进程、CLI 工具的内存占用,这些指标的改善对用户体验的影响远超单纯的吞吐量数字。
下一步值得关注:
- Bun 是否会发布 Rust 重写后的详细性能报告
- Zig 社区如何应对 Bun 离开的冲击
- AI 辅助代码迁移的方法论是否会推广到更多项目
- Bun 的 Rust 版本是否会进一步降低 unsafe 代码比例
这次迁移是一个转折点。它告诉我们,在系统编程领域,没有永恒的选择,只有最适合当下的选择。Rust 赢了今天,但下一个十年呢?没有人知道答案。唯一确定的是,工具在进化,开发者需要持续学习。
参考来源:
- Jarred Sumner (Bun 创始人) 社交媒体公告, 2026-05-11
- Bun GitHub: https://github.com/oven-sh/bun (90,566 ⭐)
- Bun v1.3.14 Release Notes: https://bun.com/blog/bun-v1.3.14
- Bun 官方文档: https://bun.com/docs
- Hacker News 技术讨论帖