# Install benchmarks (/docs/benchmarks)





Tables show median peak RSS and wall time from ten attempts per result. Lower is better. **Bold** marks the lowest median in each column.

Measured on **September 28, 2026**, on an **Apple M5 Pro with 48 GiB RAM**.

Benchmark script: [`run-t3-install-six-states.mjs`](https://github.com/lpm-dev/rust-client/blob/main/bench/scripts/run-t3-install-six-states.mjs).

## First install [#first-install]

No lockfile, a cold dependency cache, and no installed tree.

<BenchmarkTable caption="First install results">
  | Package manager                                                                    | Median peak RSS (MiB) | Median wall time (ms) |
  | ---------------------------------------------------------------------------------- | --------------------: | --------------------: |
  | <PackageManagerLabel manager="lpm">LPM CLI</PackageManagerLabel>                   |             **355.6** |           **1,594.5** |
  | <PackageManagerLabel manager="bun">Bun</PackageManagerLabel>                       |                 393.5 |                 1,825 |
  | <PackageManagerLabel manager="firewall">LPM Firewall Enabled</PackageManagerLabel> |                 383.7 |                 2,171 |
  | <PackageManagerLabel manager="pnpm">pnpm</PackageManagerLabel>                     |                 624.4 |                 4,174 |
  | <PackageManagerLabel manager="upm">UPM</PackageManagerLabel>                       |               1,125.0 |               4,431.5 |
  | <PackageManagerLabel manager="yarn">Yarn</PackageManagerLabel>                     |               1,750.6 |                 6,055 |
  | <PackageManagerLabel manager="deno">Deno</PackageManagerLabel> ¹                   |                 710.7 |                 8,156 |
  | <PackageManagerLabel manager="vlt">vlt</PackageManagerLabel>                       |               1,540.4 |               8,495.5 |
  | <PackageManagerLabel manager="nub">Nub</PackageManagerLabel>                       |                 917.9 |              10,834.5 |
  | <PackageManagerLabel manager="npm">npm</PackageManagerLabel>                       |                 863.2 |              13,787.5 |
</BenchmarkTable>

¹ Deno completed **9/10** first-install attempts. One attempt timed out after **180,002 ms** and has no RSS value. Its medians use the nine successful attempts. Every other result on this page has **10/10** successes.

## Fresh / warm [#fresh--warm]

No lockfile, a warm dependency cache, and no installed tree. The manager resolves dependencies again with cached package data.

<BenchmarkTable caption="Fresh / warm results">
  | Package manager                                                                    | Median peak RSS (MiB) | Median wall time (ms) |
  | ---------------------------------------------------------------------------------- | --------------------: | --------------------: |
  | <PackageManagerLabel manager="lpm">LPM CLI</PackageManagerLabel>                   |                  90.4 |                **66** |
  | <PackageManagerLabel manager="bun">Bun</PackageManagerLabel>                       |              **49.6** |                 191.5 |
  | <PackageManagerLabel manager="deno">Deno</PackageManagerLabel>                     |                 230.9 |                 222.5 |
  | <PackageManagerLabel manager="firewall">LPM Firewall Enabled</PackageManagerLabel> |                  96.0 |                 321.5 |
  | <PackageManagerLabel manager="pnpm">pnpm</PackageManagerLabel>                     |                 123.5 |                   355 |
  | <PackageManagerLabel manager="yarn">Yarn</PackageManagerLabel>                     |                 520.2 |                 1,169 |
  | <PackageManagerLabel manager="vlt">vlt</PackageManagerLabel>                       |                 507.7 |                 1,352 |
  | <PackageManagerLabel manager="nub">Nub</PackageManagerLabel>                       |                 483.6 |               1,457.5 |
  | <PackageManagerLabel manager="upm">UPM</PackageManagerLabel>                       |                 391.4 |                 2,276 |
  | <PackageManagerLabel manager="npm">npm</PackageManagerLabel>                       |               1,448.7 |               3,318.5 |
</BenchmarkTable>

## CI cold [#ci-cold]

An existing lockfile, a cold dependency cache, and no installed tree.

<BenchmarkTable caption="CI cold results">
  | Package manager                                                                    | Median peak RSS (MiB) | Median wall time (ms) |
  | ---------------------------------------------------------------------------------- | --------------------: | --------------------: |
  | <PackageManagerLabel manager="lpm">LPM CLI</PackageManagerLabel>                   |                 239.0 |           **1,374.5** |
  | <PackageManagerLabel manager="bun">Bun</PackageManagerLabel>                       |             **129.7** |                 1,538 |
  | <PackageManagerLabel manager="firewall">LPM Firewall Enabled</PackageManagerLabel> |                 258.3 |                 1,797 |
  | <PackageManagerLabel manager="deno">Deno</PackageManagerLabel>                     |                 536.0 |               1,897.5 |
  | <PackageManagerLabel manager="npm">npm</PackageManagerLabel>                       |                 395.3 |               2,655.5 |
  | <PackageManagerLabel manager="yarn">Yarn</PackageManagerLabel>                     |                 556.9 |               2,661.5 |
  | <PackageManagerLabel manager="vlt">vlt</PackageManagerLabel>                       |                 936.9 |                 2,753 |
  | <PackageManagerLabel manager="upm">UPM</PackageManagerLabel>                       |                 860.6 |               3,081.5 |
  | <PackageManagerLabel manager="nub">Nub</PackageManagerLabel>                       |                 472.8 |               3,441.5 |
  | <PackageManagerLabel manager="pnpm">pnpm</PackageManagerLabel>                     |                 481.9 |               3,455.5 |
</BenchmarkTable>

The CI labels describe the initial files and cache. Each manager uses its normal install command and its own lockfile, rather than a dedicated `ci` command.

## CI warm [#ci-warm]

An existing lockfile, a warm dependency cache, and no installed tree.

<BenchmarkTable caption="CI warm results">
  | Package manager                                                                    | Median peak RSS (MiB) | Median wall time (ms) |
  | ---------------------------------------------------------------------------------- | --------------------: | --------------------: |
  | <PackageManagerLabel manager="lpm">LPM CLI</PackageManagerLabel>                   |                  61.6 |               **102** |
  | <PackageManagerLabel manager="bun">Bun</PackageManagerLabel>                       |               **7.2** |                 186.5 |
  | <PackageManagerLabel manager="deno">Deno</PackageManagerLabel>                     |                  16.0 |                 190.5 |
  | <PackageManagerLabel manager="pnpm">pnpm</PackageManagerLabel>                     |                  60.8 |                 329.5 |
  | <PackageManagerLabel manager="firewall">LPM Firewall Enabled</PackageManagerLabel> |                  59.0 |                 387.5 |
  | <PackageManagerLabel manager="nub">Nub</PackageManagerLabel>                       |                  82.9 |                 390.5 |
  | <PackageManagerLabel manager="yarn">Yarn</PackageManagerLabel>                     |                 231.1 |                 654.5 |
  | <PackageManagerLabel manager="vlt">vlt</PackageManagerLabel>                       |                 503.2 |                 1,394 |
  | <PackageManagerLabel manager="upm">UPM</PackageManagerLabel>                       |                 128.0 |               2,049.5 |
  | <PackageManagerLabel manager="npm">npm</PackageManagerLabel>                       |                 865.9 |                 2,293 |
</BenchmarkTable>

## Installed / cache gone [#installed--cache-gone]

An existing lockfile and installed tree, with the dependency cache removed. LPM CLI retains its backing content store because installed symlinks depend on it. Only its ephemeral cache is removed.

<BenchmarkTable caption="Installed / cache gone results">
  | Package manager                                                                    | Median peak RSS (MiB) | Median wall time (ms) |
  | ---------------------------------------------------------------------------------- | --------------------: | --------------------: |
  | <PackageManagerLabel manager="deno">Deno</PackageManagerLabel>                     |                  14.6 |                 **8** |
  | <PackageManagerLabel manager="pnpm">pnpm</PackageManagerLabel>                     |                  18.5 |                    10 |
  | <PackageManagerLabel manager="lpm">LPM CLI</PackageManagerLabel>                   |                  25.3 |                    12 |
  | <PackageManagerLabel manager="firewall">LPM Firewall Enabled</PackageManagerLabel> |                  25.5 |                    12 |
  | <PackageManagerLabel manager="bun">Bun</PackageManagerLabel>                       |               **7.9** |                    19 |
  | <PackageManagerLabel manager="upm">UPM</PackageManagerLabel>                       |                  49.0 |                    29 |
  | <PackageManagerLabel manager="nub">Nub</PackageManagerLabel>                       |                  55.3 |                   131 |
  | <PackageManagerLabel manager="vlt">vlt</PackageManagerLabel>                       |                 104.6 |                 162.5 |
  | <PackageManagerLabel manager="npm">npm</PackageManagerLabel>                       |                 158.7 |                 667.5 |
  | <PackageManagerLabel manager="yarn">Yarn</PackageManagerLabel>                     |                 546.2 |               1,748.5 |
</BenchmarkTable>

## Up to date [#up-to-date]

An existing lockfile, a warm dependency cache, and an installed tree. No project files changed.

<BenchmarkTable caption="Up to date results">
  | Package manager                                                                    | Median peak RSS (MiB) | Median wall time (ms) |
  | ---------------------------------------------------------------------------------- | --------------------: | --------------------: |
  | <PackageManagerLabel manager="deno">Deno</PackageManagerLabel>                     |                  14.6 |                 **9** |
  | <PackageManagerLabel manager="yarn">Yarn</PackageManagerLabel>                     |                  21.3 |                   9.5 |
  | <PackageManagerLabel manager="pnpm">pnpm</PackageManagerLabel>                     |                  18.5 |                    10 |
  | <PackageManagerLabel manager="lpm">LPM CLI</PackageManagerLabel>                   |                  25.5 |                    12 |
  | <PackageManagerLabel manager="firewall">LPM Firewall Enabled</PackageManagerLabel> |                  25.5 |                    12 |
  | <PackageManagerLabel manager="bun">Bun</PackageManagerLabel>                       |               **7.9** |                    19 |
  | <PackageManagerLabel manager="upm">UPM</PackageManagerLabel>                       |                  49.0 |                    29 |
  | <PackageManagerLabel manager="nub">Nub</PackageManagerLabel>                       |                  67.6 |                 129.5 |
  | <PackageManagerLabel manager="vlt">vlt</PackageManagerLabel>                       |                 104.6 |                 163.5 |
  | <PackageManagerLabel manager="npm">npm</PackageManagerLabel>                       |                 149.2 |                 440.5 |
</BenchmarkTable>

The small results in the last two tables include process startup and timing-wrapper overhead. Differences of a few milliseconds do not establish a stable ranking.

## Versions and host [#versions-and-host]

| Package manager      | Measured version                                    |
| -------------------- | --------------------------------------------------- |
| LPM CLI              | 0.78.0                                              |
| LPM Firewall Enabled | LPM CLI 0.78.0, monitor mode                        |
| Bun                  | 1.4.2                                               |
| pnpm                 | 12.6.0, native executable                           |
| npm                  | 12.1.0                                              |
| Nub                  | 0.9.5                                               |
| Deno                 | 2.9.7                                               |
| vlt                  | 1.2.0                                               |
| UPM                  | 1.2.0                                               |
| Yarn                 | 6.0.0-rc.22, native preview executable              |
| Aube                 | 2.5.1, blocked during preflight (no scored timings) |

The host ran macOS on arm64, with Node.js 24.19.0 and AC power. LPM CLI used a release build of commit [`5cc8869`](https://github.com/lpm-dev/rust-client/commit/5cc8869c5a4c03b04788a80c5dc648098df295e3), built with Rust 1.94.0. Executable hashes matched before and after the run.

Aube rejected `next-auth@5.0.0-beta.30` under its default trust policy, with `ERR_AUBE_TRUST_DOWNGRADE`. This policy block is not a timing result or evidence that the package is malicious. The benchmark did not bypass the policy.

## Methodology [#methodology]

The T3 fixture contains **25 direct dependencies and development dependencies**, including Next.js, React, tRPC, Drizzle, and TypeScript. The baseline contains **540 scored attempts: 539 successes and one timeout**. The separate firewall run adds **60 successful scored installs**. Medians use successful installs only. No slow scored samples were discarded.

Preparation and cache cleanup occur outside the measured interval. The harness rotates manager order and state order across rounds. Each manager has an isolated home and cache, with `CI=1` and `NO_COLOR=1`. Cold means empty dependency caches, not empty operating-system or CDN caches.

Peak RSS comes from `/usr/bin/time -l`. It is a memory high-water mark, not the simultaneous memory total for a process tree. Detached vlt workers are not fully represented. The harness drains those workers outside the foreground measurement.

Lifecycle scripts remained disabled. Release-age and security policies were not normalized across managers. No proxy or LPM CLI concurrency override was present at launch.

| Manager              | Benchmark configuration                                                                                                                                                  |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| LPM CLI              | JSON output, V2 store, `--no-security-summary`, `--no-skills`, and `--no-editor-setup`. Dependency scripts remained blocked. Release cooldown and LPM Firewall were off. |
| LPM Firewall Enabled | The same LPM CLI configuration, with [LPM Firewall](/docs/guides/firewall) in `monitor` mode and `package_only` lookups.                                                 |
| Bun                  | `--ignore-scripts`. No release-age override.                                                                                                                             |
| pnpm                 | `--ignore-scripts`, silent reporter, and an isolated store. No release-age override.                                                                                     |
| npm                  | `--ignore-scripts`, `--no-fund`, and silent logs. Default audit behavior remained enabled.                                                                               |
| Nub                  | `--ignore-scripts` and `--prefer-frozen-lockfile`. Its one-day release-age policy remained enforced.                                                                     |
| Deno                 | `--node-modules-dir=auto`, without script permission or a release-age override.                                                                                          |
| vlt                  | Explicit public npm registry and matching `npm` registry alias, with an isolated cache. Dependency scripts remained blocked.                                             |
| UPM                  | An isolated store, without a release-age override. Dependency scripts remained disabled.                                                                                 |
| Yarn                 | The `node-modules` linker, with scripts and immutable installs disabled. No release-age override.                                                                        |

Each run includes 18 separate LPM CLI timing diagnostics, excluded from these tables. Nub has separate measurements despite its shared package-manager engine.

## Limits of this run [#limits-of-this-run]

* **Different dependency graphs.** Deno selected PostCSS 8.5.23. The other measured managers selected 8.5.28. Transitive versions also differ.
* **A release-age boundary.** Nub paused after three preparation failures while Sharp and an optional native dependency reached one day old. The run resumed with unchanged policies and preserved samples. Nub lockfiles can contain different Sharp versions before and after the pause.
* **Timeout interference.** The Deno timeout left a child process until manual cleanup. That process adds possible interference to later measurements. The corrected harness handles this case in future runs.
* **Background activity.** macOS indexing and other services stayed active. Host snapshots do not establish interference for each install.
* **Small sample count.** Ten attempts describe a median, not a precise tail estimate. Manager positions are not perfectly balanced across ten rounds and nine managers.
* **Install checks only.** All successful installs contained the 25 direct manifests and resolved `next/package.json`. These checks do not establish that the application builds or runs.

An earlier run stopped after a vlt worker-cleanup race. None of its 36 measurements contributes to this page. This run also differs from earlier published benchmarks in manager versions, registry data, dependency graphs, and host activity.

## See also [#see-also]

* [Compared to npm, pnpm, and Bun](/docs/comparison)
* [Package installation](/docs/packages/install)
* [Content-addressable store](/docs/packages/content-addressable-store)
