Skip to content

Bun 은 속도를 위해 설계되었습니다. 핫 패스는 광범위하게 프로파일링되고 벤치마킹됩니다. Bun 의 모든 공개 벤치마크의 소스 코드는 Bun 저장소의 /bench 디렉토리에서 찾을 수 있습니다.

시간 측정

정확하게 시간을 측정하기 위해 Bun 은 두 가지 런타임 API 함수를 제공합니다.

  1. 웹 표준 performance.now() 함수
  2. Bun.nanoseconds() - performance.now() 와 유사하지만 애플리케이션이 시작된 이후의 현재 시간을 나노초 단위로 반환합니다. performance.timeOrigin 을 사용하여 이를 Unix 타임스탬프로 변환할 수 있습니다.

벤치마킹 도구

자신의 벤치마크를 작성할 때 올바른 도구를 선택하는 것이 중요합니다.

  • 마이크로 벤치마크의 경우, 범용 도구로 mitata 가 좋습니다.
  • 부하 테스트의 경우, 결과가 왜곡되지 않으려면 적어도 Bun.serve() 만큼 빠른 HTTP 벤치마킹 도구를 사용해야 합니다. autocannon 과 같은 일부 인기 있는 Node.js 기반 벤치마킹 도구는 충분히 빠르지 않습니다. 다음 도구 중 하나를 권장합니다.
  • 스크립트나 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 파일을 엽니다.

  1. 개발자 도구 열기
  2. "Timeline" 클릭
  3. 왼쪽 메뉴에서 "JavaScript Allocations" 클릭. 모든 타임라인을 표시하려면 연필 아이콘을 클릭해야 할 수 있습니다.
  4. "Import"를 클릭하고 힙 스냅샷 JSON 선택

가져오면 다음과 같은 내용이 표시됩니다.

웹 디버거 는 실행 중인 디버그 세션의 메모리 사용량을 추적하고 검사할 수 있는 타임라인 기능도 제공합니다.

네이티브 힙 통계

Bun 은 다른 힙을 위해 mimalloc 을 사용합니다. JavaScript 가 아닌 메모리 사용량 요약을 보고하려면 MIMALLOC_SHOW_STATS=1 환경 변수를 설정하면 종료 시 통계가 출력됩니다.

sh
MIMALLOC_SHOW_STATS=1 bun script.js
txt
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
bun --cpu-prof script.js

이 명령은 Chrome DevTools(성능 탭 → 프로필 로드) 나 VS Code 의 CPU 프로파일러에서 열 수 있는 .cpuprofile 파일을 생성합니다.

옵션

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>출력 디렉토리 설정

Bun by www.bunjs.com.cn 편집