> ## Documentation Index
> Fetch the complete documentation index at: https://bun.zhcndoc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 性能基准测试

> 如何对 Bun 进行基准测试

Bun 以速度为设计目标。关键路径经过广泛的性能分析和基准测试。所有 Bun 公共基准测试的源代码都可以在 Bun 仓库的 [`/bench`](https://github.com/oven-sh/bun/tree/main/bench) 目录中找到。

## 测量时间

为了精确测量时间，Bun 提供了两个运行时 API 函数：

1. Web 标准的 [`performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now) 函数
2. `Bun.nanoseconds()`，类似于 `performance.now()`，但它返回应用程序启动以来的当前时间，单位为纳秒。你可以使用 `performance.timeOrigin` 将其转换为 Unix 时间戳。

## 基准测试工具

编写自己的基准测试时，选择合适的工具非常重要。

* 对于微基准测试，一个很好的通用工具是 [`mitata`](https://github.com/evanwashere/mitata)。
* 对于负载测试，你**必须使用**至少与 `Bun.serve()` 同样快速的 HTTP 基准测试工具，否则你的结果会受到影响。一些流行的基于 Node.js 的基准测试工具如 [`autocannon`](https://github.com/mcollina/autocannon) 速度不够。我们推荐以下工具之一：
  * [`bombardier`](https://github.com/codesenberg/bombardier)
  * [`oha`](https://github.com/hatoo/oha)
  * [`http_load_test`](https://github.com/uNetworking/uSockets/blob/master/examples/http_load_test.c)
* 对于基准测试脚本或 CLI 命令，我们推荐 [`hyperfine`](https://github.com/sharkdp/hyperfine)。

## 测量内存使用

Bun 有两个堆。一个堆用于 JavaScript 运行时，另一个堆用于其他所有内容。

### JavaScript 堆统计

`bun:jsc` 模块暴露了一些用于测量内存使用的函数：

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
import { heapStats } from "bun:jsc";
console.log(heapStats());
```

<Accordion title="查看示例统计">
  ```ts expandable icon="https://mintcdn.com/bun-zhcndoc/cnUTwgMuf4cCrwC-/icons/typescript.svg?fit=max&auto=format&n=cnUTwgMuf4cCrwC-&q=85&s=e7767043c9e885c34f2d6c8fe2a95217" theme={"theme":{"light":"github-light","dark":"dracula"}}
  {
    heapSize: 1657575,
    heapCapacity: 2872775,
    extraMemorySize: 598199,
    objectCount: 13790,
    protectedObjectCount: 62,
    globalObjectCount: 1,
    protectedGlobalObjectCount: 1,
    // 堆中每种对象类型的计数
    objectTypeCounts: {
      CallbackObject: 25,
      FunctionExecutable: 2078,
      AsyncGeneratorFunction: 2,
      'RegExp String Iterator': 1,
      FunctionCodeBlock: 188,
      ModuleProgramExecutable: 13,
      String: 1,
      UnlinkedModuleProgramCodeBlock: 13,
      JSON: 1,
      AsyncGenerator: 1,
      Symbol: 1,
      GetterSetter: 68,
      ImportMeta: 10,
      DOMAttributeGetterSetter: 1,
      UnlinkedFunctionCodeBlock: 174,
      RegExp: 52,
      ModuleLoader: 1,
      Intl: 1,
      WeakMap: 4,
      Generator: 2,
      PropertyTable: 95,
      'Array Iterator': 1,
      JSLexicalEnvironment: 75,
      UnlinkedFunctionExecutable: 2067,
      WeakSet: 1,
      console: 1,
      Map: 23,
      SparseArrayValueMap: 14,
      StructureChain: 19,
      Set: 18,
      'String Iterator': 1,
      FunctionRareData: 3,
      JSGlobalLexicalEnvironment: 1,
      Object: 481,
      BigInt: 2,
      StructureRareData: 55,
      Array: 179,
      AbortController: 2,
      ModuleNamespaceObject: 11,
      ShadowRealm: 1,
      'Immutable Butterfly': 103,
      Primordials: 1,
      'Set Iterator': 1,
      JSGlobalProxy: 1,
      AsyncFromSyncIterator: 1,
      ModuleRecord: 13,
      FinalizationRegistry: 1,
      AsyncIterator: 1,
      InternalPromise: 22,
      Iterator: 1,
      CustomGetterSetter: 65,
      Promise: 19,
      WeakRef: 1,
      InternalPromisePrototype: 1,
      Function: 2381,
      AsyncFunction: 2,
      GlobalObject: 1,
      ArrayBuffer: 2,
      Boolean: 1,
      Math: 1,
      CallbackConstructor: 1,
      Error: 2,
      JSModuleEnvironment: 13,
      WebAssembly: 1,
      HashMapBucket: 300,
      Callee: 3,
      symbol: 37,
      string: 2484,
      Performance: 1,
      ModuleProgramCodeBlock: 12,
      JSSourceCode: 13,
      JSPropertyNameEnumerator: 3,
      NativeExecutable: 290,
      Number: 1,
      Structure: 1550,
      SymbolTable: 108,
      GeneratorFunction: 2,
      'Map Iterator': 1
    },
    protectedObjectTypeCounts: {
      CallbackConstructor: 1,
      BigInt: 1,
      RegExp: 2,
      GlobalObject: 1,
      UnlinkedModuleProgramCodeBlock: 13,
      HashMapBucket: 2,
      Structure: 41,
      JSPropertyNameEnumerator: 1
    }
  }
  ```
</Accordion>

JavaScript 是一种垃圾回收语言，不是计数引用。对象在所有情况下不立即释放是正常且正确的，尽管对象永远不被释放是不正常的。

要强制手动运行垃圾回收：

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
Bun.gc(true); // 同步执行
Bun.gc(false); // 异步执行
```

堆快照让你能够检查哪些对象没有被释放。你可以使用 `bun:jsc` 模块生成堆快照，然后用 Safari 或 WebKit GTK 开发者工具查看。生成堆快照：

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
import { generateHeapSnapshot } from "bun";

const snapshot = generateHeapSnapshot();
await Bun.write("heap.json", JSON.stringify(snapshot, null, 2));
```

要查看快照，在 Safari 开发者工具（或 WebKit GTK）中打开 `heap.json` 文件：

1. 打开开发者工具
2. 点击「Timeline」（时间轴）
3. 在左侧菜单点击「JavaScript Allocations」（JavaScript 分配）。可能需要点击铅笔图标才能显示所有时间轴
4. 点击「Import」（导入），选择你的堆快照 JSON

<Frame>
  <img src="https://user-images.githubusercontent.com/709451/204428943-ba999e8f-8984-4f23-97cb-b4e3e280363e.png" alt="导入堆快照" />
</Frame>

导入后，你应该看到类似以下界面：

<Frame>
  <img alt="在 Safari 中查看堆快照" src="https://user-images.githubusercontent.com/709451/204429337-b0d8935f-3509-4071-b991-217794d1fb27.png" caption="在 Safari 开发者工具中查看堆快照" />
</Frame>

> [网页调试器](/runtime/debugger#inspect) 也提供时间轴功能，允许你追踪并检查运行中的调试会话的内存使用情况。

### 本地堆统计

Bun 另外使用 mimalloc 管理其他堆。要报告非 JavaScript 内存使用的汇总信息，设置环境变量 `MIMALLOC_SHOW_STATS=1`，退出时会打印统计信息。

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
MIMALLOC_SHOW_STATS=1 bun script.js
```

```txt theme={"theme":{"light":"github-light","dark":"dracula"}}
heap stats:    peak      total      freed    current       unit      count
  reserved:   64.0 MiB   64.0 MiB      0       64.0 MiB                        not all freed!
 committed:   64.0 MiB   64.0 MiB      0       64.0 MiB                        not all freed!
     reset:      0          0          0          0                            ok
   touched:  128.5 KiB  128.5 KiB    5.4 MiB   -5.3 MiB                        ok
  segments:      1          1          0          1                            not all freed!
-abandoned:      0          0          0          0                            ok
   -cached:      0          0          0          0                            ok
     pages:      0          0         53        -53                            ok
-abandoned:      0          0          0          0                            ok
 -extended:      0
 -noretire:      0
     mmaps:      0
   commits:      0
   threads:      0          0          0          0                            ok
  searches:     0.0 avg
numa nodes:       1
   elapsed:       0.068 s
   process: user: 0.061 s, system: 0.014 s, faults: 0, rss: 57.4 MiB, commit: 64.0 MiB
```

## CPU 性能分析

使用 `--cpu-prof` 标志分析 JavaScript 执行性能，以识别性能瓶颈。

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun --cpu-prof script.js
```

这会生成一个 `.cpuprofile` 文件，你可以在 Chrome DevTools（性能标签页 → 加载配置文件）或 VS Code 的 CPU 分析器中打开。

### Markdown 输出

使用 `--cpu-prof-md` 来生成 markdown 格式的 CPU 分析报告，这种格式便于 grep，且适合大型语言模型（LLM）分析：

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun --cpu-prof-md script.js
```

你也可以同时使用 `--cpu-prof` 和 `--cpu-prof-md` 来同时生成两种格式：

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun --cpu-prof --cpu-prof-md script.js
```

还可以通过环境变量 `BUN_OPTIONS` 来触发分析：

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
BUN_OPTIONS="--cpu-prof-md" bun script.js
```

### 选项

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun --cpu-prof --cpu-prof-name my-profile.cpuprofile script.js
bun --cpu-prof --cpu-prof-dir ./profiles script.js
```

| 标志                           | 说明                                           |
| ---------------------------- | -------------------------------------------- |
| `--cpu-prof`                 | 生成 `.cpuprofile` JSON 文件（Chrome DevTools 格式） |
| `--cpu-prof-md`              | 生成 markdown 格式的 CPU 分析报告                     |
| `--cpu-prof-name <filename>` | 设置输出文件名                                      |
| `--cpu-prof-dir <dir>`       | 设置输出目录                                       |

## 堆分析

退出时生成堆快照以分析内存使用并发现内存泄漏。

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun --heap-prof script.js
```

这将生成一个 V8 `.heapsnapshot` 文件，可以在 Chrome DevTools（Memory 标签页 → 加载）中加载。

### Markdown 输出

使用 `--heap-prof-md` 来生成 CLI 友好的 markdown 堆分析报告：

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun --heap-prof-md script.js
```

<Note>如果同时指定了 `--heap-prof` 和 `--heap-prof-md`，则以 markdown 格式为准。</Note>

### 选项

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun --heap-prof --heap-prof-name my-snapshot.heapsnapshot script.js
bun --heap-prof --heap-prof-dir ./profiles script.js
```

| 标志                            | 说明                          |
| ----------------------------- | --------------------------- |
| `--heap-prof`                 | 退出时生成 V8 `.heapsnapshot` 文件 |
| `--heap-prof-md`              | 退出时生成 markdown 格式的堆分析报告     |
| `--heap-prof-name <filename>` | 设置输出文件名                     |
| `--heap-prof-dir <dir>`       | 设置输出目录                      |
