lpm bench
Run project benchmarks with Vitest or a package script, including selected workspace members.
Use lpm bench to measure code performance with the benchmark runner declared by your project.
lpm bench [OPTIONS] [ARGS]...Quickstart
lpm install -D vitest
lpm bench
lpm bench src/parser.bench.ts| Mode | Command |
|---|---|
| Run the current package once | lpm bench |
| Run every workspace member | lpm bench --all |
| Run selected members | lpm bench --filter parser |
| Watch one member | lpm bench --filter parser -- --watch |
| Get a JSON result | lpm --json bench |
Runner selection
If vitest appears in dependencies or devDependencies, LPM CLI runs vitest bench --run.
Otherwise, it runs the bench script from package.json.
A declared Vitest dependency takes priority over the script.
Detection does not install a runner. If the selected executable is missing, run lpm install. For explicit package-script execution, use lpm run bench.
Project configuration
lpm.json has no dedicated bench section.
Project environment configuration and managed runtime pins still apply.
{
"runtime": { "node": "22" },
"env": { "bench": ".env.bench" }
}For package-script fallback, tasks.bench.env takes priority over env.bench.
The script uses prebench and postbench hooks and npm lifecycle variables.
A failed phase stops later phases.
Extra arguments apply to the main script.
Direct Vitest execution uses the default project environment.
Both paths apply environment schemas and managed runtime selection.
Workspace members inherit root runtime pins and can override each runtime locally.
A strict engines.node mismatch stops the run before the benchmark starts.
The dedicated command does not use task commands, task caching, or task dependencies. Use lpm run for those workflows. See managed runtimes for automatic downloads and fallback behavior.
Write a benchmark
import { bench, describe } from 'vitest';
const input = '{"name":"example","count":100}';
describe('parse configuration', () => {
bench('JSON.parse', () => {
JSON.parse(input);
});
});lpm bench src/parser.bench.tsFor another framework, define a package script:
{
"scripts": {
"bench": "node benchmarks/parser.mjs"
}
}lpm run benchIf Vitest is absent from the manifest, lpm bench also uses this script. The script controls its own benchmark behavior and must exit for a finite CI run.
Watch and CI
Vitest benchmarks run once by default, including in an interactive terminal.
An explicit watch request removes the default --run argument.
lpm bench -- --watch
lpm bench --filter parser -- --watch
lpm --json bench --allA workspace watch request can select exactly one member. LPM CLI rejects requests that select multiple members. An explicit long watch flag with an empty selection reports that there is nothing to watch.
Vitest short-option bundles such as -uw also request watch mode.
Tokens after a second -- belong to the runner and do not select watch mode.
Use --watch=false to disable Vitest watch mode.
Vitest treats values such as --watch=off and --watch=0 as enabled.
Put benchmark options after --:
lpm bench -- --reporter=json --outputFile=bench-results.jsonThe runner writes its own report file.
Global --json controls the LPM CLI result envelope.
Workspaces
lpm bench --all
lpm bench --filter '@scope/*'
lpm bench --filter parser --filter serializer
lpm bench --filter-prod ...shared
lpm bench --affected --base origin/main
lpm bench --filter parser --fail-if-no-match
lpm bench --all --workspace-concurrency 1Detection runs separately for each selected member. Members run in dependency order. Independent members can run together. A failed member does not stop the remaining selected members.
--all cannot combine with filters or --affected.
Filters and --affected combine as a union.
--filter-prod excludes development edges from dependency closures.
Concurrency uses the CLI flag, then root lpm.toml [workspace].concurrency, then global workspace-concurrency, then available parallelism.
This limit does not control the benchmark runner's own workers.
For measurements that require an idle machine, run one member at a time.
See workspace filters.
Output and recovery
Human mode streams benchmark output to the terminal.
With --json, single-package and workspace runs emit one result after completion.
Failed members include captured output or a launch error.
Successful members omit captured output.
Each captured stream has a 10 MiB limit, and JSON mode closes stdin.
A single-package run preserves the runner or hook exit code.
If any selected member fails, a workspace run exits with status 1.
Each failed member retains its own exit code.
A launch or configuration failure has exit_code: null and an error message.
Failures before member preparation use the global error object.
On Unix, stop signals trigger child cleanup before LPM CLI exits.
SIGINT produces status 130, and SIGTERM produces 143.
A daemon that detaches and outlives its parent manages its own shutdown.
If no runner exists, install Vitest or define a bench script.
If a workspace filter matches no members, add --fail-if-no-match to catch the mismatch in CI.
See test and bench runners for shared environment, runtime, and cleanup behavior.
Flags
| Flag | Effect |
|---|---|
--all | Select every workspace member |
--filter <FILTER> | Select members with the workspace filter grammar. Repeat to combine selections |
--filter-prod <FILTER_PROD> | Select members with production dependency closures |
--affected | Select members affected by Git changes |
--base <BASE> | Set the Git base for --affected. Default: main |
--changed-files-ignore-pattern <CHANGED_FILES_IGNORE_PATTERN> | Ignore matching changed paths during Git-based selection |
--test-pattern <TEST_PATTERN> | Treat matching changed paths as test-only during affected selection |
--fail-if-no-match | If no workspace member matches, fail |
--workspace-concurrency <N> | Limit concurrent workspace members |
Runner flags belong after --.
See global flags.
See also
- lpm test — test runners and coverage
- lpm run — package scripts and configured tasks
- Test and bench runners — shared execution behavior
- Workspaces — filters and dependency selection