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 模塊提供了一些用於測量內存使用的函數:
ts
import { heapStats } from "bun:jsc";
console.log(heapStats());查看示例統計
ts
{
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
}
}JavaScript 是一種垃圾回收語言,而不是引用計數語言。在某些情況下,對象不會立即釋放是正常且正確的,盡管對象永遠不被釋放是不正常的。
要手動強制運行垃圾回收:
ts
Bun.gc(true); // 同步
Bun.gc(false); // 異步堆快照讓你檢查哪些對象沒有被釋放。你可以使用 bun:jsc 模塊獲取堆快照,然後使用 Safari 或 WebKit GTK 開發者工具查看它。要生成堆快照:
ts
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"。它可能不可見,直到你點擊鉛筆圖標顯示所有時間線
- 點擊 "Import" 並選擇你的堆快照 JSON
導入後,你應該看到類似這樣的內容:
Web 調試器 也提供時間線功能,允許你跟蹤和檢查運行中調試會話的內存使用情況。
原生堆統計
Bun 使用 mimalloc 作為另一個堆。要報告非 JavaScript 內存使用的摘要,設置 MIMALLOC_SHOW_STATS=1 環境變量,統計信息將在退出時打印。
sh
MIMALLOC_SHOW_STATS=1 bun script.jstxt
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 MiBCPU 分析
使用 --cpu-prof 標志分析 JavaScript 執行以識別性能瓶頸。
sh
bun --cpu-prof script.js這會生成一個 .cpuprofile 文件,你可以在 Chrome DevTools(Performance 標簽頁 → Load profile)或 VS Code 的 CPU 分析器中打開它。
選項
sh
bun --cpu-prof --cpu-prof-name my-profile.cpuprofile script.js
bun --cpu-prof --cpu-prof-dir ./profiles script.js| 標志 | 描述 |
|---|---|
--cpu-prof | 啟用分析 |
--cpu-prof-name <filename> | 設置輸出文件名 |
--cpu-prof-dir <dir> | 設置輸出目錄 |