Regression Detection & CI Baselines
Performance testing in CI often suffers from high false-positive rates due to noisy VM neighbors, variable CPU clock speeds, and thermal throttling.
pytest-async-benchmark solves this by combining baseline comparison with rigorous non-parametric statistical testing. It only fails your CI pipeline when a slowdown is both substantive (exceeds your configured threshold) and statistically significant (p < 0.05).
Saving Runs
To record benchmark runs for comparison, use the --async-bench-autosave flag:
pytest --async-bench-autosaveThis saves run results to .async_benchmarks/ with numbered filenames (e.g. 0001_initial.json, 0002_refactor.json). Each saved file records:
- Complete distribution metrics for every benchmark.
- All individual raw duration samples.
- Host machine metadata (CPU, architecture, Python version, OS).
- Current Git commit SHA, branch name, and dirty-state flag.
Comparing Against Saved Baselines
To compare the current test run against the most recent saved baseline:
pytest --async-bench-compareOr compare against a specific saved baseline by number or name:
pytest --async-bench-compare=0001Pytest prints a side-by-side terminal comparison table highlighting percentage changes:

Failing CI on Regressions
To prevent performance regressions from landing on main, configure --async-bench-compare-fail:
# Fail if median latency regresses by more than 10%
pytest --async-bench-compare --async-bench-compare-fail=median:10%
# Fail if mean latency regresses by more than 15%
pytest --async-bench-compare --async-bench-compare-fail=mean:15%The Mann-Whitney U Test (Zero Flakiness)
A simple percentage threshold like +10% will periodically fail in CI due to transient host load.
To eliminate flaky CI failures, pytest-async-benchmark runs a one-sided Mann-Whitney U test across the per-call timing samples of both runs:
- Threshold Check: Is the current median/mean higher than baseline by at least the specified percentage?
- Significance Check: Are the sample distributions statistically distinct at
p < 0.05?
If latency increased by 11% but the variance across samples is high ($p \ge 0.05$), the runner recognizes that the difference may be random noise and does not fail your build. Only when the regression is confirmed with 95% statistical confidence does pytest exit with a non-zero code.
Exporting Machine-Readable JSON
Export raw benchmark results for dashboard ingestion or PR comments:
pytest --async-bench-json=benchmark_results.jsonThe exported JSON file contains structured records for every benchmark, including git commit metadata, hardware specs, and per-call samples.