Skip to content

Bun está diseñado para la velocidad. Las rutas críticas están extensamente perfiladas y evaluadas mediante benchmarking. El código fuente de todos los benchmarks públicos de Bun se encuentra en el directorio /bench del repositorio de Bun.

Medición del tiempo

Para medir el tiempo con precisión, Bun ofrece dos funciones de API de tiempo de ejecución:

  1. La función estándar web performance.now()
  2. Bun.nanoseconds() que es similar a performance.now() excepto que devuelve el tiempo actual desde que se inició la aplicación en nanosegundos. Puedes usar performance.timeOrigin para convertir esto a una marca de tiempo Unix.

Herramientas de benchmarking

Al escribir tus propios benchmarks, es importante elegir la herramienta adecuada.

  • Para microbenchmarks, una herramienta de propósito general excelente es mitata.
  • Para pruebas de carga, debes usar una herramienta de benchmarking HTTP que sea al menos tan rápida como Bun.serve(), o tus resultados estarán sesgados. Algunas herramientas de benchmarking populares basadas en Node.js como autocannon no son lo suficientemente rápidas. Recomendamos una de las siguientes:
  • Para benchmarks de scripts o comandos CLI, recomendamos hyperfine.

Medición del uso de memoria

Bun tiene dos heaps. Un heap es para el runtime de JavaScript y el otro heap es para todo lo demás.

Estadísticas del heap de JavaScript

El módulo bun:jsc expone algunas funciones para medir el uso de memoria:

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

Ver estadísticas de ejemplo

ts
{
  heapSize: 1657575,
  heapCapacity: 2872775,
  extraMemorySize: 598199,
  objectCount: 13790,
  protectedObjectCount: 62,
  globalObjectCount: 1,
  protectedGlobalObjectCount: 1,
  // Un conteo de cada tipo de objeto en el 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 es un lenguaje con recolección de basura, no con conteo de referencias. Es normal y correcto que los objetos no se liberen inmediatamente en todos los casos, aunque no es normal que los objetos nunca se liberen.

Para forzar la ejecución manual de la recolección de basura:

ts
Bun.gc(true); // síncrono
Bun.gc(false); // asíncrono

Las instantáneas del heap te permiten inspeccionar qué objetos no se están liberando. Puedes usar el módulo bun:jsc para tomar una instantánea del heap y luego verla con las herramientas de desarrollo de Safari o WebKit GTK. Para generar una instantánea del heap:

ts
import { generateHeapSnapshot } from "bun";

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

Para ver la instantánea, abre el archivo heap.json en las Herramientas de Desarrollo de Safari (o WebKit GTK)

  1. Abre las Herramientas de Desarrollo
  2. Haz clic en "Timeline"
  3. Haz clic en "JavaScript Allocations" en el menú de la izquierda. Puede que no sea visible hasta que hagas clic en el ícono del lápiz para mostrar todas las líneas de tiempo
  4. Haz clic en "Import" y selecciona tu instantánea del heap en JSON

Una vez importada, deberías ver algo como esto:

El depurador web también ofrece la función de timeline que te permite rastrear y examinar el uso de memoria de la sesión de depuración en ejecución.

Estadísticas del heap nativo

Bun usa mimalloc para el otro heap. Para reportar un resumen del uso de memoria no JavaScript, establece la variable de entorno MIMALLOC_SHOW_STATS=1 y las estadísticas se imprimirán al salir.

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

Perfilado de CPU

Perfilaa la ejecución de JavaScript para identificar cuellos de botella de rendimiento con la bandera --cpu-prof.

sh
bun --cpu-prof script.js

Esto genera un archivo .cpuprofile que puedes abrir en Chrome DevTools (pestaña Rendimiento → Cargar perfil) o en el perfilador de CPU de VS Code.

Opciones

sh
bun --cpu-prof --cpu-prof-name my-profile.cpuprofile script.js
bun --cpu-prof --cpu-prof-dir ./profiles script.js
BanderaDescripción
--cpu-profHabilitar perfilado
--cpu-prof-name <filename>Establecer nombre del archivo de salida
--cpu-prof-dir <dir>Establecer directorio de salida

Bun por www.bunjs.com.cn editar