Skip to main content

benchmatrix

CI Documentation Docker CodeQL OpenSSF Scorecard Workflow lint Python 3.11-3.14 Typed with basedpyright Linted with Ruff Coverage gate: 95% SBOM: CycloneDX 1.6

Benchmark matrices for Python projects that need performance data they can trust, compare, and parse

[!TIP] Read the benchmatrix documentation for the quickstart, usage guides, and API reference.

benchmatrix sits on top of pytest-benchmark and adds the layer that benchmark suites usually grow by hand: implementation-by-case matrices, strict JSON-safe metadata, metric-aware result parsing, and concise display of saved benchmark runs.

Build repeatable suites Keep metrics honest Parse saved runs
Generate pytest benchmark tests across implementations, cases, and metric views. Separate latency, throughput, and local distribution comparisons instead of mixing unlike numbers. Load benchmatrix-tagged pytest-benchmark JSON rows into structured Python objects.

Quick Start

Create a benchmark matrix from ordinary synchronous callables in a pytest file:

from benchmatrix import BenchmarkCase, make_benchmark_test

implementations = {
    "builtin": sum,
    "loop": lambda vs: sum(v for v in vs),
}

cases = [
    BenchmarkCase.from_values(
        "small",
        list(range(100)),
        work_units=100,
        work_unit_name="items",
    ),
]

test_sum_matrix = make_benchmark_test(implementations, cases)

Run it with pytest-benchmark and keep the machine-readable output:

uv run pytest tests/test_sum_benchmark.py --benchmark-json benchmark.json

Read the run back and compare it with a controlled baseline:

from benchmatrix import display_benchmark_rows, load_benchmark_run

baseline = load_benchmark_run("baseline.json")
candidate = load_benchmark_run("benchmark.json")

display_benchmark_rows(candidate.rows)
comparison = baseline.compare_to(candidate)

if not comparison.passed:
    for cell in comparison.regressed:
        print(cell.implementation_name, cell.case_name, cell.metric_name)

Collect a controlled repeated-run group without managing output names by hand:

benchmatrix collect --runs 5 --output benchmark-runs -- \
    uv run pytest tests/test_sum_benchmark.py

The collection directory contains numbered pytest-benchmark JSON files and an atomic benchmatrix-manifest.json. Collection can recover without discarding its audit trail:

# Continue attempts after an interrupted process.
benchmatrix collect --resume --output benchmark-runs

# Append bounded retries while preserving every failed attempt.
benchmatrix collect --retry-failed --output benchmark-runs

The manifest command and working directory are reused, accepted files are revalidated, and retry attempts append to the audit trail instead of replacing failures.

Compare collection directories directly:

benchmatrix compare baseline-runs candidate-runs \
    --threshold 5% \
    --fail-on-regression

Existing automation can still combine individual repeated files:

benchmatrix compare baseline-1.json candidate-1.json \
    --baseline-run baseline-2.json \
    --candidate-run candidate-2.json \
    --threshold 5% \
    --fail-on-regression

Keep comparison policy under review with the benchmark suite:

[tool.benchmatrix.evidence]
minimum_runs = 3

[tool.benchmatrix.regression]
default_threshold_percent = 5.0

[tool.benchmatrix.regression.by_metric]
tail_latency = 8.0

benchmatrix compare discovers the nearest pyproject.toml. CLI policy options override their corresponding configured scalar without discarding per-metric, implementation, case, or exact-cell thresholds.

Inspect or validate that policy without running benchmarks:

benchmatrix policy show
benchmatrix policy validate --quiet

Comparison JSON is a strict, versioned decision record that can be archived and loaded independently of the original timing files:

benchmatrix compare baseline-runs candidate-runs \
    --format json > comparison.json
from benchmatrix import load_comparison_report

report = load_comparison_report("comparison.json")
print(report.schema_version, report.passed, len(report.regressed))

Publish the same report as Markdown or a GitHub Actions step summary:

benchmatrix compare baseline-runs candidate-runs --format markdown
benchmatrix compare baseline-runs candidate-runs --github-summary

Why It Exists

pytest-benchmark owns timing, calibration, statistics, terminal reporting, and JSON export. benchmatrix owns the repeatable structure around those timings.

Need benchmatrix gives you
Compare multiple implementations One generated pytest benchmark matrix with optional untimed output validation.
Track what each timing means JSON-safe invocation metadata with implementation, case, and metric identity.
Report different metric views Single-call latency, logical-work throughput, and local tail-latency summaries.
Reuse benchmark output Manifest-backed collection, repeated-run evidence diagnostics, environment checks, regression policies, and matrix comparisons.

benchmatrix is intentionally narrow: it benchmarks synchronous Python callables. It is not a load-testing framework, production latency monitor, or replacement for pytest-benchmark.

Interpreting Results

Benchmark output is environment-specific. Compare results only between runs from controlled environments, and keep the pytest-benchmark JSON output with the hardware, Python, dependency, and CI context that produced it.

Use metric names as part of every comparison:

  • single-call latency compares one completed synchronous target call;
  • batch throughput compares logical work per second when work_units is meaningful and consistent;
  • tail-latency summaries describe local distribution shape for a benchmark run, not production service latency.

Install

Install the released package with uv:

uv add benchmatrix

or with pip:

python -m pip install benchmatrix

For local development from this repository:

make ready

Documentation

The documentation source lives under docs/. The top-level Markdown files are short project entry points; detailed guides, explanations, references, and runbooks live in the MkDocs documentation.

Start here Use it for
First benchmark A complete first benchmark from test file to parsed JSON.
Create a benchmark matrix Cases, work units, fresh inputs, and synchronous target wrappers.
Parse benchmark results Loading and displaying benchmatrix-tagged pytest-benchmark JSON.
Performance model What the metrics mean and what they do not prove.
Development Local setup, test commands, and repository layout.
Compatibility Supported Python versions, API stability, and support policy.
Publishing Release artifacts, draft releases, PyPI publishing, and verification.
Configuration and automation Make targets, CI workflows, Docker checks, docs, and SBOM generation.

The MkDocs site builds in strict mode and generates API reference pages from the package docstrings.

Project Links

License

benchmatrix is distributed under the MIT License.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

benchmatrix-1.0.0.tar.gz (162.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

benchmatrix-1.0.0-py3-none-any.whl (69.2 kB view details)

Uploaded Python 3

File details

Details for the file benchmatrix-1.0.0.tar.gz.

File metadata

  • Download URL: benchmatrix-1.0.0.tar.gz
  • Upload date:
  • Size: 162.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for benchmatrix-1.0.0.tar.gz
Algorithm Hash digest
SHA256 027b0c1d73170072234e1db6cb9a74b56ec3f65f9181f840b21967da10ff7832
MD5 15929b03516b527f8c6080714e792133
BLAKE2b-256 7d49e52a643959acad4938fe9fbe8c09a15c8471f52c8a1d38a26bfe39b856b1

See more details on using hashes here.

Provenance

The following attestation bundles were made for benchmatrix-1.0.0.tar.gz:

Publisher: release.yml on ryancswallace/benchmatrix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file benchmatrix-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: benchmatrix-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 69.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for benchmatrix-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cc3b506b597c6981f1d037c422223f6836b5ee7b129f543082bd05f1115e66e2
MD5 54f94bd9a4398ddbf4b34d1df05bc9d5
BLAKE2b-256 c3fd2d7166db6e8a30d414ec7a24933f84d58c3d5aaee8673a2ad7164adcc87f

See more details on using hashes here.

Provenance

The following attestation bundles were made for benchmatrix-1.0.0-py3-none-any.whl:

Publisher: release.yml on ryancswallace/benchmatrix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.2.1

2 files

This release

1.0.0 This release

2 files

0.3.0

2 files

0.2.4

2 files

0.2.3

2 files

0.2.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page