O Bun é projetado para velocidade. Caminhos críticos são extensivamente perfilados e benchmarked. O código-fonte de todos os benchmarks públicos do Bun pode ser encontrado no diretório /bench do repositório do Bun.
Medindo tempo
Para medir o tempo com precisão, o Bun oferece duas APIs de tempo de execução:
- A função padrão Web
performance.now() Bun.nanoseconds()que é similar aoperformance.now()exceto que retorna o tempo atual desde que a aplicação iniciou em nanosegundos. Você pode usarperformance.timeOriginpara converter isso para um timestamp Unix.
Ferramentas de benchmark
Ao escrever seus próprios benchmarks, é importante escolher a ferramenta certa.
- Para microbenchmarks, uma ótima ferramenta de propósito geral é
mitata. - Para teste de carga, você deve usar uma ferramenta de benchmark HTTP que seja pelo menos tão rápida quanto
Bun.serve(), ou seus resultados serão distorcidos. Algumas ferramentas populares baseadas em Node.js comoautocannonnão são rápidas o suficiente. Recomendamos uma das seguintes: - Para benchmark de scripts ou comandos CLI, recomendamos
hyperfine.
Medindo uso de memória
O Bun possui dois heaps. Um heap é para o runtime JavaScript e o outro heap é para todo o resto.
Estatísticas do heap JavaScript
O módulo bun:jsc expõe algumas funções para medir uso de memória:
import { heapStats } from "bun:jsc";
console.log(heapStats());Ver estatísticas de exemplo
{
heapSize: 1657575,
heapCapacity: 2872775,
extraMemorySize: 598199,
objectCount: 13790,
protectedObjectCount: 62,
globalObjectCount: 1,
protectedGlobalObjectCount: 1,
// Uma contagem de cada tipo de objeto no 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 é uma linguagem com coleta de lixo, não contagem de referência. É normal e correto que objetos não sejam liberados imediatamente em todos os casos, embora não seja normal que objetos nunca sejam liberados.
Para forçar a coleta de lixo manualmente:
Bun.gc(true); // síncrono
Bun.gc(false); // assíncronoSnapshots do heap permitem inspecionar quais objetos não estão sendo liberados. Você pode usar o módulo bun:jsc para tirar um snapshot do heap e depois visualizá-lo com as ferramentas de desenvolvedor do Safari ou WebKit GTK. Para gerar um snapshot do heap:
import { generateHeapSnapshot } from "bun";
const snapshot = generateHeapSnapshot();
await Bun.write("heap.json", JSON.stringify(snapshot, null, 2));Para visualizar o snapshot, abra o arquivo heap.json nas Ferramentas de Desenvolvedor do Safari (ou WebKit GTK)
- Abra as Ferramentas de Desenvolvedor
- Clique em "Timeline"
- Clique em "JavaScript Allocations" no menu à esquerda. Pode não estar visível até você clicar no ícone de lápis para mostrar todas as timelines
- Clique em "Import" e selecione seu JSON de snapshot do heap
Uma vez importado, você deve ver algo como isto:
O depurador web também oferece o recurso de timeline que permite rastrear e examinar o uso de memória da sessão de depuração em execução.
Estatísticas do heap nativo
O Bun usa mimalloc para o outro heap. Para reportar um resumo do uso de memória não-JavaScript, defina a variável de ambiente MIMALLOC_SHOW_STATS=1 e as estatísticas serão impressas na saída.
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 MiBPerfil de CPU
Perfile a execução JavaScript para identificar gargalos de desempenho com a flag --cpu-prof.
bun --cpu-prof script.jsIsso gera um arquivo .cpuprofile que você pode abrir no Chrome DevTools (aba Performance → Carregar perfil) ou no profiler de CPU do VS Code.
Opções
bun --cpu-prof --cpu-prof-name my-profile.cpuprofile script.js
bun --cpu-prof --cpu-prof-dir ./profiles script.js| Flag | Descrição |
|---|---|
--cpu-prof | Habilitar perfil |
--cpu-prof-name <filename> | Definir nome do arquivo de saída |
--cpu-prof-dir <dir> | Definir diretório de saída |