執行環境套件管理器打包器測試執行器程式碼檢查格式化指南參考部落格意見回饋

效能基準測試

如何對 Bun 進行基準測試

Bun 專為速度而設計。我們會對熱點路徑進行廣泛的效能分析和基準測試。Bun 所有公開基準測試的原始碼都位於 Bun 儲存庫的 /bench 目錄中。

測量時間

為了精確測量時間,Bun 提供了兩個執行環境 API:

  1. 符合 Web 標準的 performance.now() 函式
  2. Bun.nanoseconds(),它類似於 performance.now(),但傳回的是應用程式啟動以來經過的時間,單位為納秒。使用 performance.timeOrigin 可將其轉換為 Unix 時間戳。

基準測試工具

  • 對於微基準測試,我們推薦使用 mitata。
  • 對於負載測試,你 必須使用 至少與 Bun.serve() 一樣快的 HTTP 基準測試工具,否則測試結果會產生偏差。一些流行的基於 Node.js 的基準測試工具(例如 autocannon)速度不夠快。我們推薦使用以下工具之一:
  • 對於基準測試指令碼或 CLI 命令,我們推薦使用 hyperfine。

測量記憶體使用

Bun 有兩個堆:一個用於 JavaScript 執行環境,另一個用於其他所有內容。

JavaScript 堆統計

bun:jsc 模組暴露了一些用於測量記憶體使用的函式:

TypeScript
import { heapStats } from "bun:jsc";
console.log(heapStats());
檢視範例統計
expandable
{
  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 是一種垃圾回收語言,而非引用計數語言。物件在某些情況下不會立即釋放,這是正常且正確的;但物件永遠不被釋放則不正常。

要強制手動執行垃圾回收:

TypeScript
Bun.gc(true); // 同步執行
Bun.gc(false); // 非同步執行

堆快照可以顯示哪些物件沒有被釋放。使用 Bun.generateHeapSnapshot() 獲取堆快照,然後使用 Safari 或 WebKit GTK 開發者工具檢視。生成堆快照:

TypeScript
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
匯入堆快照

匯入後,你應該看到類似以下介面:

在 Safari 中檢視堆快照

Web 偵錯程式的時間軸還會跟蹤正在執行的除錯會話的記憶體使用情況。

本地堆統計

Bun 使用 mimalloc 管理另一個堆。要列印非 JavaScript 記憶體使用情況的摘要,請呼叫 Bun.unsafe.mimallocDump()。

TypeScript
Bun.unsafe.mimallocDump();
Text
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 執行效能,以識別效能瓶頸。

terminal
bun --cpu-prof script.js

--cpu-prof 會寫入一個 .cpuprofile 檔案,你可以在 Chrome DevTools(效能面板 → 載入設定檔)或 VS Code 的 CPU 分析器中開啟該檔案。

Markdown 輸出

使用 --cpu-prof-md 來生成 Markdown 格式的 CPU 分析報告,這種格式便於 grep,且適合大型語言模型(LLM)分析:

terminal
bun --cpu-prof-md script.js

同時使用 --cpu-prof 和 --cpu-prof-md 可一次生成兩種格式:

terminal
bun --cpu-prof --cpu-prof-md script.js

你也可以通過 BUN_OPTIONS 環境變數傳遞該標誌:

terminal
BUN_OPTIONS="--cpu-prof-md" bun script.js

選項

terminal
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>設定輸出目錄

堆分析

退出時寫入堆分析檔案,以分析記憶體使用情況並查詢記憶體洩漏。

terminal
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 堆分析報告:

terminal
bun --heap-prof-md script.js

選項

terminal
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 沒有可應用間隔的分配取樣功能)