skills/bun-project-benchmarking/SKILL.md
How to benchmark Bun
npx skillsauth add jarle/bun-skills Bun BenchmarkingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
How to benchmark Bun
Bun is designed for speed. Hot paths are extensively profiled and benchmarked. The source code for all of Bun's public benchmarks can be found in the /bench directory of the Bun repo.
To precisely measure time, Bun offers two runtime APIs functions:
performance.now() functionBun.nanoseconds() which is similar to performance.now() except it returns the current time since the application started in nanoseconds. You can use performance.timeOrigin to convert this to a Unix timestamp.When writing your own benchmarks, it's important to choose the right tool.
mitata.Bun.serve(), or your results will be skewed. Some popular Node.js-based benchmarking tools like autocannon are not fast enough. We recommend one of the following:
bombardierohahttp_load_testhyperfine.Bun has two heaps. One heap is for the JavaScript runtime and the other heap is for everything else.
The bun:jsc module exposes a few functions for measuring memory usage:
import { heapStats } from "bun:jsc";
console.log(heapStats());
<Accordion title="View example statistics">
```ts expandable icon="https://mintcdn.com/bun-1dd33a4e/nIz6GtMH5K-dfXeV/icons/typescript.svg?fit=max&auto=format&n=nIz6GtMH5K-dfXeV&q=85&s=5d73d76daf7eb7b158469d8c30d349b0" theme={"theme":{"light":"github-light","dark":"dracula"}}
{
heapSize: 1657575,
heapCapacity: 2872775,
extraMemorySize: 598199,
objectCount: 13790,
protectedObjectCount: 62,
globalObjectCount: 1,
protectedGlobalObjectCount: 1,
// A count of every object type in the 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
}
}
```
</Accordion>
JavaScript is a garbage-collected language, not reference counted. It's normal and correct for objects to not be freed immediately in all cases, though it's not normal for objects to never be freed.
To force garbage collection to run manually:
Bun.gc(true); // synchronous
Bun.gc(false); // asynchronous
Heap snapshots let you inspect what objects are not being freed. You can use the bun:jsc module to take a heap snapshot and then view it with Safari or WebKit GTK developer tools. To generate a heap snapshot:
import { generateHeapSnapshot } from "bun";
const snapshot = generateHeapSnapshot();
await Bun.write("heap.json", JSON.stringify(snapshot, null, 2));
To view the snapshot, open the heap.json file in Safari's Developer Tools (or WebKit GTK)
Once imported, you should see something like this:
<Frame> <img alt="Viewing heap snapshot in Safari" src="https://user-images.githubusercontent.com/709451/204429337-b0d8935f-3509-4071-b991-217794d1fb27.png" caption="Viewing heap snapshot in Safari Dev Tools" /> </Frame>The web debugger also offers the timeline feature which allows you to track and examine the memory usage of the running debug session.
Bun uses mimalloc for the other heap. To report a summary of non-JavaScript memory usage, set the MIMALLOC_SHOW_STATS=1 environment variable. and stats will print on exit.
MIMALLOC_SHOW_STATS=1 bun script.js
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
Profile JavaScript execution to identify performance bottlenecks with the --cpu-prof flag.
bun --cpu-prof script.js
This generates a .cpuprofile file you can open in Chrome DevTools (Performance tab → Load profile) or VS Code's CPU profiler.
Use --cpu-prof-md to generate a markdown CPU profile, which is grep-friendly and designed for LLM analysis:
bun --cpu-prof-md script.js
Both --cpu-prof and --cpu-prof-md can be used together to generate both formats at once:
bun --cpu-prof --cpu-prof-md script.js
You can also trigger profiling via the BUN_OPTIONS environment variable:
BUN_OPTIONS="--cpu-prof-md" bun script.js
bun --cpu-prof --cpu-prof-name my-profile.cpuprofile script.js
bun --cpu-prof --cpu-prof-dir ./profiles script.js
| Flag | Description |
| ---------------------------- | ----------------------------------------------------------- |
| --cpu-prof | Generate a .cpuprofile JSON file (Chrome DevTools format) |
| --cpu-prof-md | Generate a markdown CPU profile (grep/LLM-friendly) |
| --cpu-prof-name <filename> | Set output filename |
| --cpu-prof-dir <dir> | Set output directory |
Generate heap snapshots on exit to analyze memory usage and find memory leaks.
bun --heap-prof script.js
This generates a V8 .heapsnapshot file that can be loaded in Chrome DevTools (Memory tab → Load).
Use --heap-prof-md to generate a markdown heap profile for CLI analysis:
bun --heap-prof-md script.js
<Note>If both --heap-prof and --heap-prof-md are specified, the markdown format is used.</Note>
bun --heap-prof --heap-prof-name my-snapshot.heapsnapshot script.js
bun --heap-prof --heap-prof-dir ./profiles script.js
| Flag | Description |
| ----------------------------- | ------------------------------------------ |
| --heap-prof | Generate a V8 .heapsnapshot file on exit |
| --heap-prof-md | Generate a markdown heap profile on exit |
| --heap-prof-name <filename> | Set output filename |
| --heap-prof-dir <dir> | Set output directory |
development
Using TypeScript with Bun, including type definitions and compiler options
development
Learn how to write tests using Bun's Jest-compatible API with support for async tests, timeouts, and various test modifiers
testing
Learn how to use snapshot testing in Bun to save and compare output between test runs
testing
Learn about Bun test's runtime integration, environment variables, timeouts, and error handling