Skip to content

Benchmarks

The numbers below are measured end-to-end against the same medium-sized real-world fixture — ~1400 real-world packages — using hyperfine to time each scenario under identical conditions.

Methodology

Every scenario assumes a committed lockfile is present. The main axis is how warm the tool's cache/store is before the command runs; rows use each tool's default install model, which means aube's global virtual store is enabled and pnpm's comparable feature is left at pnpm's default of off. Warm clears node_modules but keeps each tool's store/cache populated; cold wipes the store and cache too. The fixture, scripts, and raw hyperfine output live at benchmarks/. Reproduce locally with mise run bench.

aube 1.18.0 bun 1.3.14 deno 2.8.2 pnpm 11.5.2 npm 11.9.0 yarn 4.16.0node 24.14.0
Fresh install (warm cache)
aube
272ms
bun
2.00s
deno
1.33s
pnpm
2.34s
npm
7.14s
yarn
8.86s
Fresh install (cold cache)
aube
7.95s
bun
5.78s
deno
8.15s
pnpm
15.87s
npm
9.51s
yarn
13.19s
npm install && npm run test
aube
9ms
bun
41ms
deno
84ms
pnpm
335ms
npm
745ms
yarn
1.18s

The chart highlights the warm-cache, no-node_modules install case.

Last updated: 2026-06-05 · Source: benchmarks/results.json, regenerated by mise run bench:bump.

Why it's faster

aube starts from pnpm's isolated symlink model — a global content-addressable store plus a per-project virtual store — and enables a global virtual store by default for local installs. pnpm supports a similar global virtual store, but leaves it off by default, so the benchmark rows compare the tools as users get them out of the box.

Scenarios

  • Fresh install (warm cache) — frozen lockfile, node_modules wiped, store and packument cache warm.
  • Fresh install (cold cache) — frozen lockfile but the store, packument cache, and node_modules are all wiped. Measures registry fetch, store import, and link/materialization work from scratch.
  • npm install && npm run test (already installed) — models the developer loop after dependencies are already installed. Each timed run repeats the tool's normal "install if needed, then run tests" command. aube can skip the install work when its install-state file is fresh; other tools still revalidate their lockfile or install state before dispatching the script. The fixture's test script is a no-op node -e, so this scenario mostly measures install short-circuiting and script dispatch.

Reproducing

sh
# One-shot: runs the package managers through the full scenario matrix,
# writes results to benchmarks/results.json, and emits the markdown
# summary to stdout.
mise run bench:bump

The task calls benchmarks/bench.sh through mise x, installs the benchmark toolchain declared on the task, sets RUNS=10 WARMUP=3, and points RESULTS_JSON at benchmarks/results.json so the file is rewritten in-place. Commit the updated JSON to refresh the chart above — the VitePress data loader at docs/benchmarks.data.ts reads it at build time, so you don't need to edit benchmarks.md or hand-write any chart data.

Benchmark runs use a hermetic local registry with the link shaped to a fixed 500mbit / 50ms baseline — a "fast home broadband" profile — so two runs on different ISPs or CI runners produce comparable numbers:

sh
flock /tmp/aube-bench.lock mise run bench
MIT Licenseen.devCopyright © 2026 en.dev