性能基准测试
如何对 Bun 进行基准测试
Bun 专为速度而设计。我们会对热点路径进行广泛的性能分析和基准测试。Bun 所有公开基准测试的源代码都位于 Bun 仓库的 /bench 目录中。
测量时间
为了精确测量时间,Bun 提供了两个运行时 API:
- 符合 Web 标准的
performance.now()函数 Bun.nanoseconds(),它类似于performance.now(),但返回的是应用程序启动以来经过的时间,单位为纳秒。使用performance.timeOrigin可将其转换为 Unix 时间戳。
基准测试工具
- 对于微基准测试,我们推荐使用
mitata。 - 对于负载测试,你 必须使用 至少与
Bun.serve()一样快的 HTTP 基准测试工具,否则测试结果会产生偏差。一些流行的基于 Node.js 的基准测试工具(例如autocannon)速度不够快。我们推荐使用以下工具之一: - 对于基准测试脚本或 CLI 命令,我们推荐使用
hyperfine。
测量内存使用
Bun 有两个堆:一个用于 JavaScript 运行时,另一个用于其他所有内容。
JavaScript 堆统计
bun:jsc 模块暴露了一些用于测量内存使用的函数:
import { heapStats } from "bun:jsc";
console.log(heapStats());
查看示例统计
{
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,
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
}
}
JavaScript 是一种垃圾回收语言,而非引用计数语言。对象在某些情况下不会立即释放,这是正常且正确的;但对象永远不被释放则不正常。
要强制手动运行垃圾回收:
Bun.gc(true); // 同步执行
Bun.gc(false); // 异步执行
堆快照可以显示哪些对象没有被释放。使用 Bun.generateHeapSnapshot() 获取堆快照,然后使用 Safari 或 WebKit GTK 开发者工具查看。生成堆快照:
import { generateHeapSnapshot } from "bun";
const snapshot = generateHeapSnapshot();
await Bun.write("heap.json", JSON.stringify(snapshot, null, 2));
要查看快照,请在 Safari 的开发者工具(或 WebKit GTK)中打开 heap.json 文件:
- 打开开发者工具
- 点击「Timeline」(时间轴)
- 在左侧菜单点击「JavaScript Allocations」(JavaScript 分配)。可能需要点击铅笔图标才能显示所有时间轴
- 点击「Import」(导入),选择你的堆快照 JSON

导入后,你应该看到类似以下界面:

Web 调试器的时间轴还会跟踪正在运行的调试会话的内存使用情况。
本地堆统计
Bun 使用 mimalloc 管理另一个堆。要打印非 JavaScript 内存使用情况的摘要,请调用 Bun.unsafe.mimallocDump()。
Bun.unsafe.mimallocDump();
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 执行性能,以识别性能瓶颈。
bun --cpu-prof script.js
--cpu-prof 会写入一个 .cpuprofile 文件,你可以在 Chrome DevTools(性能面板 → 加载配置文件)或 VS Code 的 CPU 分析器中打开该文件。
Markdown 输出
使用 --cpu-prof-md 来生成 Markdown 格式的 CPU 分析报告,这种格式便于 grep,且适合大型语言模型(LLM)分析:
bun --cpu-prof-md script.js
同时使用 --cpu-prof 和 --cpu-prof-md 可一次生成两种格式:
bun --cpu-prof --cpu-prof-md script.js
你也可以通过 BUN_OPTIONS 环境变量传递该标志:
BUN_OPTIONS="--cpu-prof-md" bun script.js
选项
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> | 设置输出目录 |
堆分析
退出时写入堆分析文件,以分析内存使用情况并查找内存泄漏。
bun --heap-prof script.js
--heap-prof 会在退出时写入完整的 V8 格式堆快照,使用 Node.js 的诊断文件名格式(Heap.<yyyymmdd>.<hhmmss>.<pid>.<tid>.<seq>.heapprofile)。扩展名遵循 Node 的 --heap-prof 文件名约定。其内容与 v8.writeHeapSnapshot()/Bun.generateHeapSnapshot("v8") 相同。可通过 Chrome DevTools 的 Memory(内存)面板 → Load(加载)加载该文件。选择「All Files」(所有文件),或将文件重命名为 .heapsnapshot。
Markdown 输出
使用 --heap-prof-md 来生成适合 CLI 使用的 Markdown 堆分析报告:
bun --heap-prof-md script.js
选项
bun --heap-prof --heap-prof-name my-profile.heapprofile script.js
bun --heap-prof --heap-prof-dir ./profiles script.js
| 标志 | 说明 |
|---|---|
--heap-prof | 在退出时写入 .heapprofile 文件 |
--heap-prof-md | 在退出时生成 Markdown 堆分析文件 |
--heap-prof-name <filename> | 设置输出文件名 |
--heap-prof-dir <dir> | 设置输出目录 |
--heap-prof-interval <bytes> | 为兼容 Node.js 而接受(快照只会在退出时获取一次;JavaScriptCore 没有可应用间隔的分配采样功能) |