Run a test method N times. Get mean, median, p95, p99, min, max. Catch slow queries. Compare before/after refactors. Set performance budgets in CI. All locally, in milliseconds.
While the benchmark runs, Nimbus shows a live progress view with rolling statistics updated after each run. Press q at any time to stop early and get results from completed runs so far.
When complete, the final table shows mean, median, p95, p99, min, max, and which run was the slowest. Results are also appended to .nimbus/bench-history.jsonl for manual comparison across sessions.
# Benchmark a test method (100 runs by default)
nimbus bench AccountServiceTest.testInsertAccount
# Benchmarking AccountServiceTest.testInsertAccount - 100 runs
#
# ████████████████░░░░░░░░░░░░░░░░ 52/100 runs
#
# Mean 42ms Min 38ms
# p50 41ms Max 61ms
# p95 58ms
#
# Press q to stop early and show results so far.
# Results: AccountServiceTest.testInsertAccount (100 runs, 10 warmup discarded)
#
# Mean 42ms
# Median 41ms
# p95 58ms
# p99 61ms
# Min 38ms
# Max 67ms
#
# Slowest run: run 73 (67ms)A query that takes 5ms in dev will take 5ms on every run. Benchmark before and after adding indexes or restructuring queries.
Refactored a service class? Run bench before and after. The numbers tell you whether the change made things faster or just different.
Pipe JSON output to jq and fail the pipeline if p95 crosses a threshold. Ship slow code deliberately, not accidentally.
Add a bench step to your PR workflow. If the p99 jumps 3x between branches, you know before merge.
--runs controls how many times the test executes. The default is 100. The first 10% of runs are discarded as warmup by default - JIT effects, cold caches, and first-connection overhead skew early samples and aren't representative of steady-state performance.
Three output formats: table (human-readable, default), json (machine-readable, CI-friendly), and csv (one row per sample, for external analysis).
# 50 runs, no warmup
nimbus bench MyTest.testMethod --runs 50 --warmup=false
# JSON output
nimbus bench MyTest.testMethod --format json
# CSV output (run_number, duration_ms per row)
nimbus bench MyTest.testMethod --format csv > results.csvJSON output pipes cleanly to jq. Fail the pipeline if p95 exceeds a threshold - ship slow code deliberately, not by accident.
Results are appended to .nimbus/bench-history.jsonl after every run. Each line is a JSON object with timestamp, method, and all timing stats. Useful for trending over time in external tooling.
# Fail if p95 exceeds 100ms
nimbus bench AccountServiceTest.testQuery \
--runs 50 --format json \
| jq 'if .p95_ms > 100 then error("p95 exceeded 100ms") else . end'
# Extract just the p95 value
nimbus bench MyTest.testMethod --format json | jq '.p95_ms'
# Compare two branches
git stash
nimbus bench MyTest.testMethod --format json | jq '.mean_ms' > before.txt
git stash pop
nimbus bench MyTest.testMethod --format json | jq '.mean_ms' > after.txt
echo "before: $(cat before.txt)ms after: $(cat after.txt)ms"nimbus bench gives you the numbers to treat it like one. Pro feature.