Skip to content

Bun est conçu pour la vitesse. Les chemins critiques sont largement profilés et benchmarkés. Le code source de tous les benchmarks publics de Bun se trouve dans le répertoire /bench du dépôt Bun.

Mesurer le temps

Pour mesurer précisément le temps, Bun offre deux fonctions d'API runtime :

  1. La fonction standard Web performance.now()
  2. Bun.nanoseconds() qui est similaire à performance.now() sauf qu'elle retourne le temps actuel depuis le démarrage de l'application en nanosecondes. Vous pouvez utiliser performance.timeOrigin pour convertir cela en timestamp Unix.

Outils de benchmarking

Lors de l'écriture de vos propres benchmarks, il est important de choisir le bon outil.

  • Pour les microbenchmarks, un excellent outil polyvalent est mitata.
  • Pour les tests de charge, vous devez utiliser un outil de benchmarking HTTP qui est au moins aussi rapide que Bun.serve(), sinon vos résultats seront faussés. Certains outils de benchmarking populaires basés sur Node.js comme autocannon ne sont pas assez rapides. Nous recommandons l'un des suivants :
  • Pour benchmarker des scripts ou des commandes CLI, nous recommandons hyperfine.

Mesurer l'utilisation de la mémoire

Bun a deux tas. Un tas est pour le runtime JavaScript et l'autre tas est pour tout le reste.

Statistiques du tas JavaScript

Le module bun:jsc expose quelques fonctions pour mesurer l'utilisation de la mémoire :

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

Voir des statistiques d'exemple">

ts
{
  heapSize: 1657575,
  heapCapacity: 2872775,
  extraMemorySize: 598199,
  objectCount: 13790,
  protectedObjectCount: 62,
  globalObjectCount: 1,
  protectedGlobalObjectCount: 1,
  // Un comptage de chaque type d'objet dans le tas
  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
  }
}

Le JavaScript est un langage avec garbage collector, pas avec comptage de références. Il est normal et correct que les objets ne soient pas libérés immédiatement dans tous les cas, bien qu'il ne soit pas normal que les objets ne soient jamais libérés.

Pour forcer l'exécution du garbage collection manuellement :

ts
Bun.gc(true); // synchrone
Bun.gc(false); // asynchrone

Les instantanés du tas vous permettent d'inspecter quels objets ne sont pas libérés. Vous pouvez utiliser le module bun:jsc pour prendre un instantané du tas puis le visualiser avec les outils de développement Safari ou WebKit GTK. Pour générer un instantané du tas :

ts
import { generateHeapSnapshot } from "bun";

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

Pour visualiser l'instantané, ouvrez le fichier heap.json dans les outils de développement de Safari (ou WebKit GTK)

  1. Ouvrez les outils de développement
  2. Cliquez sur "Timeline"
  3. Cliquez sur "JavaScript Allocations" dans le menu de gauche. Il pourrait ne pas être visible jusqu'à ce que vous cliquiez sur l'icône de crayon pour afficher toutes les timelines
  4. Cliquez sur "Import" et sélectionnez votre JSON d'instantané du tas

Une fois importé, vous devriez voir quelque chose comme ceci :

Le débogueur web offre également la fonctionnalité timeline qui vous permet de suivre et d'examiner l'utilisation de la mémoire de la session de débogage en cours d'exécution.

Statistiques du tas natif

Bun utilise mimalloc pour l'autre tas. Pour afficher un résumé de l'utilisation de la mémoire non-JavaScript, définissez la variable d'environnement MIMALLOC_SHOW_STATS=1 et les statistiques seront affichées à la sortie.

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

Profilage CPU

Profilez l'exécution JavaScript pour identifier les goulots d'étranglement de performance avec le drapeau --cpu-prof.

sh
bun --cpu-prof script.js

Cela génère un fichier .cpuprofile que vous pouvez ouvrir dans Chrome DevTools (onglet Performance → Charger le profil) ou le profileur CPU de VS Code.

Options

sh
bun --cpu-prof --cpu-prof-name my-profile.cpuprofile script.js
bun --cpu-prof --cpu-prof-dir ./profiles script.js
DrapeauDescription
--cpu-profActiver le profilage
--cpu-prof-name <filename>Définir le nom du fichier de sortie
--cpu-prof-dir <dir>Définir le répertoire de sortie

Bun édité par www.bunjs.com.cn