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:
- La funzione standard Web
performance.now() Bun.nanoseconds()che è simile aperformance.now()ma restituisce il tempo corrente dall'avvio dell'applicazione in nanosecondi. Puoi usareperformance.timeOriginper 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 comeautocannonnon 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:
import { heapStats } from "bun:jsc";
console.log(heapStats());Visualizza statistiche di esempio
{
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:
Bun.gc(true); // sincrono
Bun.gc(false); // asincronoGli 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:
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)
- Apri gli Strumenti per Sviluppatori
- Clicca su "Timeline"
- Clicca su "JavaScript Allocations" nel menu a sinistra. Potrebbe non essere visibile finché non clicchi sull'icona della matita per mostrare tutte le timeline
- 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.
MIMALLOC_SHOW_STATS=1 bun script.jsheap 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 MiBProfilazione CPU
Profilare l'esecuzione JavaScript per identificare i colli di bottiglia delle prestazioni con il flag --cpu-prof.
bun --cpu-prof script.jsQuesto genera un file .cpuprofile che puoi aprire in Chrome DevTools (scheda Performance → Carica profilo) o nel profilatore CPU di VS Code.
Opzioni
bun --cpu-prof --cpu-prof-name my-profile.cpuprofile script.js
bun --cpu-prof --cpu-prof-dir ./profiles script.js| Flag | Descrizione |
|---|---|
--cpu-prof | Abilita la profilazione |
--cpu-prof-name <filename> | Imposta il nome del file di output |
--cpu-prof-dir <dir> | Imposta la directory di output |