Skip to content

Bun è progettato per la velocità. I percorsi critici sono ampiamente profilati e sottoposti a benchmark. Il codice sorgente di tutti i benchmark pubblici di Bun è disponibile nella directory /bench del repository di Bun.

Misurazione del tempo

Per misurare con precisione il tempo, Bun offre due funzioni API runtime:

  1. La funzione standard Web performance.now()
  2. Bun.nanoseconds() che è simile a performance.now() ma restituisce il tempo corrente dall'avvio dell'applicazione in nanosecondi. Puoi usare performance.timeOrigin per convertirlo in un timestamp Unix.

Strumenti di benchmark

Quando scrivi i tuoi benchmark, è importante scegliere lo strumento giusto.

  • Per i microbenchmark, uno strumento generico eccellente è mitata.
  • Per il load testing, devi usare uno strumento di benchmark HTTP che sia almeno veloce quanto Bun.serve(), altrimenti i risultati saranno distorti. Alcuni strumenti di benchmark basati su Node.js popolari come autocannon non sono abbastanza veloci. Raccomandiamo uno dei seguenti:
  • Per il benchmark di script o comandi CLI, raccomandiamo hyperfine.

Misurazione dell'uso della memoria

Bun ha due heap. Un heap è per il runtime JavaScript e l'altro heap è per tutto il resto.

Statistiche dell'heap JavaScript

Il modulo bun:jsc espone alcune funzioni per misurare l'uso della memoria:

ts
import { heapStats } from "bun:jsc";
console.log(heapStats());

Visualizza statistiche di esempio

ts
{
  heapSize: 1657575,
  heapCapacity: 2872775,
  extraMemorySize: 598199,
  objectCount: 13790,
  protectedObjectCount: 62,
  globalObjectCount: 1,
  protectedGlobalObjectCount: 1,
  // Un conteggio di ogni tipo di oggetto nell'heap
  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 è un linguaggio con garbage collection, non a conteggio dei riferimenti. È normale e corretto che gli oggetti non vengano liberati immediatamente in tutti i casi, anche se non è normale che gli oggetti non vengano mai liberati.

Per forzare manualmente l'esecuzione della garbage collection:

ts
Bun.gc(true); // sincrono
Bun.gc(false); // asincrono

Gli snapshot dell'heap ti consentono di ispezionare quali oggetti non vengono liberati. Puoi usare il modulo bun:jsc per creare uno snapshot dell'heap e poi visualizzarlo con gli strumenti per sviluppatori di Safari o WebKit GTK. Per generare uno snapshot dell'heap:

ts
import { generateHeapSnapshot } from "bun";

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

Per visualizzare lo snapshot, apri il file heap.json negli Strumenti per Sviluppatori di Safari (o WebKit GTK)

  1. Apri gli Strumenti per Sviluppatori
  2. Clicca su "Timeline"
  3. Clicca su "JavaScript Allocations" nel menu a sinistra. Potrebbe non essere visibile finché non clicchi sull'icona della matita per mostrare tutte le timeline
  4. Clicca su "Import" e seleziona il tuo snapshot dell'heap JSON

Una volta importato, dovresti vedere qualcosa del genere:

Il web debugger offre anche la funzionalità timeline che consente di tracciare ed esaminare l'uso della memoria della sessione di debug in esecuzione.

Statistiche dell'heap nativo

Bun usa mimalloc per l'altro heap. Per riportare un riepilogo dell'uso della memoria non JavaScript, imposta la variabile d'ambiente MIMALLOC_SHOW_STATS=1 e le statistiche verranno stampate all'uscita.

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

Profilazione CPU

Profilare l'esecuzione JavaScript per identificare i colli di bottiglia delle prestazioni con il flag --cpu-prof.

sh
bun --cpu-prof script.js

Questo genera un file .cpuprofile che puoi aprire in Chrome DevTools (scheda Performance → Carica profilo) o nel profilatore CPU di VS Code.

Opzioni

sh
bun --cpu-prof --cpu-prof-name my-profile.cpuprofile script.js
bun --cpu-prof --cpu-prof-dir ./profiles script.js
FlagDescrizione
--cpu-profAbilita la profilazione
--cpu-prof-name <filename>Imposta il nome del file di output
--cpu-prof-dir <dir>Imposta la directory di output

Bun a cura di www.bunjs.com.cn