Performance Regression Suite
The Kuestenlogik.Surgewave.Benchmarks.Regression CLI detects performance regressions by comparing BenchmarkDotNet results against a stored baseline. It integrates with CI to automatically flag regressions on pull requests.
Overview
The regression suite provides three commands:
| Command | Description |
|---|---|
compare |
Compare results against baseline, report regressions |
update-baseline |
Merge new results into the baseline file |
report |
Generate a Markdown regression report |
Quick Start
# Run benchmarks and produce a JSON report
dotnet run --project benchmarks/Kuestenlogik.Surgewave.Benchmarks.Unit -c Release -- \
--filter '*' --exporters json --job short --artifacts artifacts/benchmarks
# Compare against baseline
dotnet run --project benchmarks/Kuestenlogik.Surgewave.Benchmarks.Regression -c Release -- \
compare artifacts/benchmarks/*-report-full.json \
benchmarks/baselines/unit-baseline.json \
-o artifacts/regression-report.md \
--fail-on-regression
Commands
compare
Compares benchmark results against a baseline and optionally writes a Markdown report:
compare <results-json> <baseline-json> [-o report.md] [--config config.json] [--fail-on-regression]
| Flag | Description |
|---|---|
-o <path> |
Write Markdown report to file |
--config <path> |
Custom threshold configuration file |
--fail-on-regression |
Exit with code 1 if regressions are detected |
Without --fail-on-regression, the command reports regressions but exits with code 0.
update-baseline
Merges new benchmark results into an existing baseline file:
update-baseline <results-json> <baseline-json>
Existing benchmarks are updated with new values. New benchmarks are added. Benchmarks not in the current run are preserved.
report
Generates a Markdown regression report (always writes to file):
report <results-json> <baseline-json> -o report.md [--config config.json]
Threshold Configuration
Configure regression detection thresholds in a JSON config file:
{
"latencyThresholdPercent": 15.0,
"throughputThresholdPercent": 10.0,
"allocationThresholdPercent": 20.0,
"excludedBenchmarks": [
"BenchmarkWithHighVariance"
],
"categoryOverrides": {
"Serialization": {
"latencyThresholdPercent": 20.0,
"allocationThresholdPercent": 30.0
},
"Storage": {
"throughputThresholdPercent": 5.0
}
}
}
Default Thresholds
| Metric | Default Threshold | Description |
|---|---|---|
| Latency (mean time) | 15% | Flagged if mean execution time increases by more than 15% |
| Throughput (ops/sec) | 10% | Flagged if throughput drops by more than 10% |
| Allocations (bytes) | 20% | Flagged if allocations increase by more than 20% |
Per-Category Overrides
Category is derived from the benchmark's [BenchmarkCategory] attribute or the containing class name. Override specific thresholds per category while keeping global defaults for others by setting the override value; use null to fall back to the global default.
Baseline Management
Baselines are stored as JSON files (e.g., benchmarks/baselines/unit-baseline.json). To update after intentional performance changes:
dotnet run --project benchmarks/Kuestenlogik.Surgewave.Benchmarks.Regression -c Release -- \
update-baseline artifacts/benchmarks/*-report-full.json \
benchmarks/baselines/unit-baseline.json
You can also use the helper script:
.\scripts\update-benchmark-baselines.ps1
CI Integration
The benchmark-regression.yml GitHub Actions workflow runs automatically on pull requests that modify src/ or benchmarks/ files:
- Builds the benchmark project in Release mode
- Runs benchmarks with
--job shortfor CI-friendly execution time - Compares results against the committed baseline
- Uploads the regression report as a build artifact
- Fails the check if regressions exceed thresholds (via
--fail-on-regression)
# .github/workflows/benchmark-regression.yml
on:
pull_request:
branches: [main]
paths:
- 'src/**'
- 'benchmarks/**'
The workflow uses the --fail-on-regression flag, so the PR check fails if any benchmark regresses beyond the configured thresholds.
Regression Severity
Each comparison result is classified:
| Severity | Meaning |
|---|---|
None |
Within acceptable threshold |
Warning |
Close to threshold (not a failure) |
Regression |
Exceeds threshold (fails CI with --fail-on-regression) |
Next Steps
- Benchmarks - Running benchmarks manually
- Tuning Guide - Performance tuning recommendations
- Chaos Testing - Resilience testing