Skip to content

Bun 性能优化

Bun 本身已经非常快速,但通过正确的优化策略可以进一步提升性能。本章介绍 Bun 的性能调优技巧。

Bun 为什么快

架构优势

┌─────────────────────────────────────────┐
│              Bun 架构                    │
├─────────────────────────────────────────┤
│  Zig 语言编写的核心                      │
│  JavaScriptCore 引擎                     │
│  优化的系统调用                          │
│  内置功能减少依赖                        │
└─────────────────────────────────────────┘

性能对比

操作Node.jsBun提升
启动时间40ms4ms10x
包安装30s1s30x
HTTP 请求/秒50k150k3x
文件读取基准3x faster3x

HTTP 服务器优化

基本优化

typescript
const server = Bun.serve({
  port: 3000,
  
  // 使用简洁的响应
  fetch(request) {
    // ✅ 直接返回 Response
    return new Response("Hello!");
    
    // ❌ 避免不必要的异步
    // return Promise.resolve(new Response("Hello!"));
  },
});

静态响应缓存

typescript
// 预创建常用响应
const notFoundResponse = new Response("Not Found", { status: 404 });
const okResponse = new Response("OK");
const jsonHeaders = { "Content-Type": "application/json" };

const server = Bun.serve({
  port: 3000,
  
  fetch(request) {
    const url = new URL(request.url);
    
    if (url.pathname === "/health") {
      return okResponse; // 复用响应对象
    }
    
    if (url.pathname === "/api/data") {
      // 预计算的 JSON
      return new Response(cachedJsonString, { headers: jsonHeaders });
    }
    
    return notFoundResponse;
  },
});

流式响应

typescript
// 大数据使用流式响应
const server = Bun.serve({
  port: 3000,
  
  fetch(request) {
    const stream = new ReadableStream({
      async start(controller) {
        for (let i = 0; i < 1000; i++) {
          controller.enqueue(`data: ${i}\n`);
          // 不阻塞其他请求
          if (i % 100 === 0) {
            await Bun.sleep(0);
          }
        }
        controller.close();
      },
    });
    
    return new Response(stream, {
      headers: { "Content-Type": "text/event-stream" },
    });
  },
});

文件 I/O 优化

使用 Bun.file()

typescript
// ✅ 使用 Bun.file(最快)
const content = await Bun.file("./data.txt").text();

// ❌ 避免 Node.js fs(较慢)
// import { readFile } from "fs/promises";
// const content = await readFile("./data.txt", "utf-8");

批量文件操作

typescript
// ✅ 并行读取多个文件
const files = ["a.txt", "b.txt", "c.txt"];
const contents = await Promise.all(
  files.map(f => Bun.file(f).text())
);

// ❌ 避免串行读取
// for (const f of files) {
//   contents.push(await Bun.file(f).text());
// }

流式写入大文件

typescript
// 大文件使用 writer
const writer = Bun.file("./large-output.txt").writer();

for (let i = 0; i < 1000000; i++) {
  writer.write(`Line ${i}\n`);
  
  // 定期刷新缓冲区
  if (i % 10000 === 0) {
    await writer.flush();
  }
}

await writer.end();

数据库优化

SQLite 优化

typescript
import { Database } from "bun:sqlite";

const db = new Database("app.db");

// 启用 WAL 模式
db.run("PRAGMA journal_mode = WAL");
db.run("PRAGMA synchronous = NORMAL");
db.run("PRAGMA cache_size = -64000"); // 64MB 缓存
db.run("PRAGMA temp_store = MEMORY");

// 使用预处理语句
const insert = db.prepare("INSERT INTO items (name) VALUES (?)");
const select = db.prepare("SELECT * FROM items WHERE id = ?");

// 批量插入使用事务
const insertMany = db.transaction((items: string[]) => {
  for (const item of items) {
    insert.run(item);
  }
});

连接池模式

typescript
// 为高并发场景创建多个连接
class DatabasePool {
  private connections: Database[] = [];
  private index = 0;
  
  constructor(path: string, size: number = 4) {
    for (let i = 0; i < size; i++) {
      const db = new Database(path);
      db.run("PRAGMA journal_mode = WAL");
      this.connections.push(db);
    }
  }
  
  get(): Database {
    this.index = (this.index + 1) % this.connections.length;
    return this.connections[this.index];
  }
  
  close() {
    for (const conn of this.connections) {
      conn.close();
    }
  }
}

内存优化

减少内存分配

typescript
// ✅ 复用 Buffer
const buffer = new Uint8Array(1024);

function processData(data: Uint8Array) {
  // 使用预分配的 buffer
  buffer.set(data.slice(0, 1024));
  return processBuffer(buffer);
}

// ❌ 避免频繁创建新对象
// function processData(data) {
//   const buffer = new Uint8Array(1024); // 每次都分配
//   ...
// }

使用 --smol 模式

bash
# 减少内存使用(适合受限环境)
bun --smol app.ts

监控内存使用

typescript
// 定期检查内存
setInterval(() => {
  const usage = process.memoryUsage();
  console.log({
    heapUsed: `${(usage.heapUsed / 1024 / 1024).toFixed(2)} MB`,
    heapTotal: `${(usage.heapTotal / 1024 / 1024).toFixed(2)} MB`,
    external: `${(usage.external / 1024 / 1024).toFixed(2)} MB`,
  });
}, 10000);

并发优化

使用 Worker

typescript
// main.ts
const worker = new Worker("./worker.ts");

worker.postMessage({ type: "process", data: [1, 2, 3, 4, 5] });

worker.onmessage = (event) => {
  console.log("结果:", event.data);
};

// worker.ts
self.onmessage = (event) => {
  const { type, data } = event.data;
  
  if (type === "process") {
    const result = data.map((n: number) => n * 2);
    self.postMessage(result);
  }
};

并行处理

typescript
// 使用 Promise.all 并行处理
async function processItems(items: string[]) {
  const batchSize = 100;
  const batches = [];
  
  for (let i = 0; i < items.length; i += batchSize) {
    batches.push(items.slice(i, i + batchSize));
  }
  
  const results = await Promise.all(
    batches.map(batch => processBatch(batch))
  );
  
  return results.flat();
}

构建优化

生产构建

typescript
await Bun.build({
  entrypoints: ["./src/index.ts"],
  outdir: "./dist",
  
  // 生产优化
  minify: true,
  
  // Tree Shaking
  treeshaking: true,
  
  // 定义环境
  define: {
    "process.env.NODE_ENV": JSON.stringify("production"),
  },
});

代码分割

typescript
await Bun.build({
  entrypoints: ["./src/index.ts"],
  outdir: "./dist",
  splitting: true, // 自动代码分割
});

网络优化

复用连接

typescript
// 复用 HTTP 连接
const agent = {
  keepAlive: true,
  keepAliveMsecs: 30000,
};

// Bun 默认复用连接,但可以配置

压缩响应

typescript
const server = Bun.serve({
  port: 3000,
  
  async fetch(request) {
    const data = JSON.stringify(largeData);
    
    // 检查客户端是否支持压缩
    const acceptEncoding = request.headers.get("accept-encoding") || "";
    
    if (acceptEncoding.includes("gzip")) {
      const compressed = Bun.gzipSync(data);
      return new Response(compressed, {
        headers: {
          "Content-Type": "application/json",
          "Content-Encoding": "gzip",
        },
      });
    }
    
    return Response.json(largeData);
  },
});

性能分析

内置分析

bash
# 查看详细的启动时间
bun --timing app.ts

自定义计时

typescript
// 使用 console.time
console.time("operation");
await heavyOperation();
console.timeEnd("operation");

// 或使用 performance
const start = performance.now();
await heavyOperation();
const duration = performance.now() - start;
console.log(`耗时: ${duration.toFixed(2)}ms`);

基准测试

typescript
// bench.ts
import { bench, run } from "bun:test";

bench("string concatenation", () => {
  let s = "";
  for (let i = 0; i < 1000; i++) {
    s += "x";
  }
});

bench("array join", () => {
  const arr = [];
  for (let i = 0; i < 1000; i++) {
    arr.push("x");
  }
  arr.join("");
});

await run();

运行:

bash
bun run bench.ts

最佳实践清单

✅ 推荐做法

  1. 使用 Bun 原生 API

    • Bun.file() 而非 fs
    • Bun.serve() 而非 http
    • bun:sqlite 而非第三方库
  2. 减少分配

    • 复用对象和缓冲区
    • 使用对象池
    • 避免不必要的拷贝
  3. 批量处理

    • 使用事务进行数据库操作
    • 批量文件操作
    • 减少 I/O 次数
  4. 并行处理

    • Promise.all 并行请求
    • Worker 处理 CPU 密集任务
    • 流式处理大数据
  5. 合理配置

    • 启用压缩
    • 使用 WAL 模式
    • 配置缓存

❌ 避免做法

  1. 频繁创建新对象
  2. 同步阻塞操作
  3. 忽略连接复用
  4. 未优化的数据库查询
  5. 不必要的数据复制

小结

本章介绍了:

  • ✅ Bun 的性能优势
  • ✅ HTTP 服务器优化
  • ✅ 文件和数据库优化
  • ✅ 内存和并发优化
  • ✅ 构建和网络优化
  • ✅ 性能分析工具
  • ✅ 最佳实践清单

下一步

继续阅读 Node.js 兼容性 了解如何从 Node.js 迁移到 Bun。

本站内容仅供学习和研究使用。