benchmatrix 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- benchmatrix-0.2.1/.gitignore +49 -0
- benchmatrix-0.2.1/CHANGELOG.md +56 -0
- benchmatrix-0.2.1/CITATION.cff +24 -0
- benchmatrix-0.2.1/CODE_OF_CONDUCT.md +31 -0
- benchmatrix-0.2.1/CONTRIBUTING.md +66 -0
- benchmatrix-0.2.1/LICENSE +21 -0
- benchmatrix-0.2.1/PKG-INFO +154 -0
- benchmatrix-0.2.1/README.md +123 -0
- benchmatrix-0.2.1/RELEASING.md +61 -0
- benchmatrix-0.2.1/SECURITY.md +30 -0
- benchmatrix-0.2.1/docs/_scripts/gen_api_reference.py +34 -0
- benchmatrix-0.2.1/docs/changelog.md +13 -0
- benchmatrix-0.2.1/docs/contributing.md +27 -0
- benchmatrix-0.2.1/docs/development.md +106 -0
- benchmatrix-0.2.1/docs/explanation/ai.md +18 -0
- benchmatrix-0.2.1/docs/explanation/architecture.md +29 -0
- benchmatrix-0.2.1/docs/explanation/dependency-policy.md +49 -0
- benchmatrix-0.2.1/docs/explanation/deployment-environments.md +54 -0
- benchmatrix-0.2.1/docs/explanation/deprecations.md +45 -0
- benchmatrix-0.2.1/docs/explanation/first-release.md +25 -0
- benchmatrix-0.2.1/docs/explanation/github-actions-security.md +40 -0
- benchmatrix-0.2.1/docs/explanation/license-policy.md +19 -0
- benchmatrix-0.2.1/docs/explanation/lifecycle.md +53 -0
- benchmatrix-0.2.1/docs/explanation/performance.md +52 -0
- benchmatrix-0.2.1/docs/explanation/publishing.md +125 -0
- benchmatrix-0.2.1/docs/explanation/repository-health.md +18 -0
- benchmatrix-0.2.1/docs/explanation/repository-settings.md +150 -0
- benchmatrix-0.2.1/docs/explanation/secrets.md +22 -0
- benchmatrix-0.2.1/docs/explanation/threat-model.md +26 -0
- benchmatrix-0.2.1/docs/how-to/create-benchmark-matrix.md +62 -0
- benchmatrix-0.2.1/docs/how-to/parse-results.md +35 -0
- benchmatrix-0.2.1/docs/how-to/run-with-docker.md +99 -0
- benchmatrix-0.2.1/docs/how-to/troubleshooting.md +48 -0
- benchmatrix-0.2.1/docs/index.md +37 -0
- benchmatrix-0.2.1/docs/reference/compatibility.md +127 -0
- benchmatrix-0.2.1/docs/reference/configuration.md +182 -0
- benchmatrix-0.2.1/docs/reference/index.md +16 -0
- benchmatrix-0.2.1/docs/runbooks/container-release.md +72 -0
- benchmatrix-0.2.1/docs/runbooks/dependency-update.md +78 -0
- benchmatrix-0.2.1/docs/runbooks/failed-ci.md +34 -0
- benchmatrix-0.2.1/docs/runbooks/incident-response.md +32 -0
- benchmatrix-0.2.1/docs/runbooks/index.md +18 -0
- benchmatrix-0.2.1/docs/runbooks/ownership-transfer.md +27 -0
- benchmatrix-0.2.1/docs/runbooks/release.md +147 -0
- benchmatrix-0.2.1/docs/runbooks/repository-setup.md +147 -0
- benchmatrix-0.2.1/docs/runbooks/security-report.md +36 -0
- benchmatrix-0.2.1/docs/tutorials/first-benchmark.md +72 -0
- benchmatrix-0.2.1/examples/test_factorial_benchmarks.py +78 -0
- benchmatrix-0.2.1/examples/test_factorial_benchmarks_simplified.py +61 -0
- benchmatrix-0.2.1/mkdocs.yml +92 -0
- benchmatrix-0.2.1/noxfile.py +97 -0
- benchmatrix-0.2.1/pyproject.toml +185 -0
- benchmatrix-0.2.1/src/benchmatrix/__init__.py +57 -0
- benchmatrix-0.2.1/src/benchmatrix/_schema.py +79 -0
- benchmatrix-0.2.1/src/benchmatrix/bench_harness.py +1060 -0
- benchmatrix-0.2.1/src/benchmatrix/bench_results.py +536 -0
- benchmatrix-0.2.1/src/benchmatrix/exceptions.py +13 -0
- benchmatrix-0.2.1/src/benchmatrix/py.typed +0 -0
- benchmatrix-0.2.1/tests/fixtures/benchmark_results/invalid_tail_missing_data.json +20 -0
- benchmatrix-0.2.1/tests/fixtures/benchmark_results/mixed_metrics.json +56 -0
- benchmatrix-0.2.1/tests/test_bench_harness.py +615 -0
- benchmatrix-0.2.1/tests/test_bench_results.py +445 -0
- benchmatrix-0.2.1/tests/test_integration.py +185 -0
- benchmatrix-0.2.1/tests/test_properties.py +93 -0
- benchmatrix-0.2.1/tests/test_public_api.py +53 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Python bytecode and caches
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
.pytest_cache/
|
|
5
|
+
.ruff_cache/
|
|
6
|
+
.pre-commit-cache/
|
|
7
|
+
.mypy_cache/
|
|
8
|
+
.pyright/
|
|
9
|
+
.ipynb_checkpoints/
|
|
10
|
+
|
|
11
|
+
# Virtual environments
|
|
12
|
+
.nox/
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# Build artifacts
|
|
18
|
+
build/
|
|
19
|
+
dist/
|
|
20
|
+
*.egg-info/
|
|
21
|
+
site/
|
|
22
|
+
|
|
23
|
+
# Test coverage and reports
|
|
24
|
+
.coverage
|
|
25
|
+
htmlcov/
|
|
26
|
+
reports/
|
|
27
|
+
|
|
28
|
+
# Environment and secrets
|
|
29
|
+
.env
|
|
30
|
+
.env.*
|
|
31
|
+
!.env.example
|
|
32
|
+
|
|
33
|
+
# OS/editor noise
|
|
34
|
+
.DS_Store
|
|
35
|
+
Thumbs.db
|
|
36
|
+
|
|
37
|
+
# Node / npm
|
|
38
|
+
node_modules/
|
|
39
|
+
npm-debug.log*
|
|
40
|
+
yarn-debug.log*
|
|
41
|
+
yarn-error.log*
|
|
42
|
+
pnpm-debug.log*
|
|
43
|
+
.npm/
|
|
44
|
+
|
|
45
|
+
# Notes
|
|
46
|
+
TODO.md
|
|
47
|
+
|
|
48
|
+
# Generated example benchmark output
|
|
49
|
+
examples/benchmark_results/
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to benchmatrix will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The project follows [Semantic Versioning](https://semver.org/), with the
|
|
6
|
+
additional pre-1.0 compatibility expectations described in
|
|
7
|
+
[the release policy](RELEASING.md).
|
|
8
|
+
|
|
9
|
+
## Unreleased
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
## 0.2.1 - 2026-06-22
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
* Fix release and release-verify workflow bugs preventing creation of PyPI
|
|
20
|
+
releases.
|
|
21
|
+
|
|
22
|
+
## 0.2.0 - 2026-06-22
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
* Initial benchmark matrix utilities.
|
|
27
|
+
* pytest-benchmark JSON parsing and display utilities.
|
|
28
|
+
* Automated linting, typing, security, dependency, test, coverage, and package
|
|
29
|
+
validation for local development and pull requests, including scheduled
|
|
30
|
+
audits of locked dependencies for known vulnerabilities.
|
|
31
|
+
* Pre-commit automation, secret scanning, Markdown linting, GitHub Actions
|
|
32
|
+
workflow linting, and repository text and binary file attributes.
|
|
33
|
+
* MkDocs documentation site with strict builds, generated API reference pages,
|
|
34
|
+
and operational maintainer runbooks.
|
|
35
|
+
* Reproducible CycloneDX SBOM generation for locked runtime dependencies.
|
|
36
|
+
* uv-backed nox automation for supported-Python tests, quality checks, and
|
|
37
|
+
release artifact smoke testing.
|
|
38
|
+
* GitHub pull request auto-labeling and labels-as-code configuration for
|
|
39
|
+
maintainers.
|
|
40
|
+
* Dependabot automation for Python, Node, pre-commit, GitHub Actions, Docker,
|
|
41
|
+
and devcontainer dependency updates.
|
|
42
|
+
* Repository settings-as-code plus external setup checklists for branch
|
|
43
|
+
protection, security features, Pages, environments, and PyPI publishing.
|
|
44
|
+
* Focused Python dependency groups for test, lint, type, docs, security,
|
|
45
|
+
release, and automation tooling, with `dev` as the aggregate group.
|
|
46
|
+
* Compatibility, lifecycle, security-fix, release-branch, and deprecation
|
|
47
|
+
policy documentation.
|
|
48
|
+
* GitHub Actions CI/CD workflows for quality checks, multi-version and
|
|
49
|
+
cross-OS tests, docs deployment, PyPI Trusted Publishing, artifact
|
|
50
|
+
attestations, CodeQL, dependency review, OpenSSF Scorecard, and workflow
|
|
51
|
+
linting.
|
|
52
|
+
* CI test and coverage report artifacts, documentation link checking, minimum-
|
|
53
|
+
dependency tests, and post-release PyPI installation verification.
|
|
54
|
+
* Docker runtime and test images, local Docker targets, Docker-outside-of-Docker
|
|
55
|
+
devcontainer support, Dockerfile linting, GHCR publishing, image
|
|
56
|
+
SBOM/provenance, and critical-vulnerability image scanning.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use benchmatrix in your work, please cite it using this metadata."
|
|
3
|
+
title: "benchmatrix"
|
|
4
|
+
abstract: >-
|
|
5
|
+
Utilities for building pytest-benchmark benchmark matrices and parsing
|
|
6
|
+
pytest-benchmark JSON output.
|
|
7
|
+
type: software
|
|
8
|
+
authors:
|
|
9
|
+
- family-names: "Wallace"
|
|
10
|
+
given-names: "Ryan"
|
|
11
|
+
email: "ryancswallace@gmail.com"
|
|
12
|
+
alias: "ryancswallace"
|
|
13
|
+
version: 0.2.1
|
|
14
|
+
date-released: "2026-06-22"
|
|
15
|
+
license: MIT
|
|
16
|
+
repository-code: "https://github.com/ryancswallace/benchmatrix"
|
|
17
|
+
url: "https://github.com/ryancswallace/benchmatrix"
|
|
18
|
+
keywords:
|
|
19
|
+
- "python"
|
|
20
|
+
- "benchmarking"
|
|
21
|
+
- "benchmark"
|
|
22
|
+
- "performance"
|
|
23
|
+
- "pytest"
|
|
24
|
+
- "pytest-benchmark"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Code of conduct
|
|
2
|
+
|
|
3
|
+
## Our commitment
|
|
4
|
+
|
|
5
|
+
We are committed to making participation in the benchmatrix community a
|
|
6
|
+
welcoming and harassment-free experience for everyone, regardless of
|
|
7
|
+
background, identity, appearance, experience level, or ability.
|
|
8
|
+
|
|
9
|
+
## Expected behavior
|
|
10
|
+
|
|
11
|
+
Examples of behavior that contributes to a positive community include:
|
|
12
|
+
|
|
13
|
+
* being respectful, constructive, and empathetic;
|
|
14
|
+
* giving and accepting technical feedback gracefully;
|
|
15
|
+
* focusing disagreement on ideas and outcomes rather than people;
|
|
16
|
+
* taking responsibility for mistakes and learning from them.
|
|
17
|
+
|
|
18
|
+
Unacceptable behavior includes harassment, discrimination, threats, sustained
|
|
19
|
+
disruption, sexualized attention, deliberate intimidation, or publishing
|
|
20
|
+
someone's private information without permission.
|
|
21
|
+
|
|
22
|
+
## Enforcement
|
|
23
|
+
|
|
24
|
+
Report conduct concerns privately to Ryan Wallace at
|
|
25
|
+
<ryancswallace@gmail.com>. Reports will be reviewed promptly and handled as
|
|
26
|
+
confidentially as practical. The maintainer may edit or remove contributions,
|
|
27
|
+
temporarily or permanently restrict participation, or take other action
|
|
28
|
+
appropriate to the circumstances.
|
|
29
|
+
|
|
30
|
+
This policy applies in project spaces and when someone is publicly representing
|
|
31
|
+
the project.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Contributing to benchmatrix
|
|
2
|
+
|
|
3
|
+
Thanks for considering a contribution.
|
|
4
|
+
|
|
5
|
+
## Before you start
|
|
6
|
+
|
|
7
|
+
For substantial changes, open an issue first so the problem and proposed
|
|
8
|
+
direction can be discussed. Small fixes and documentation improvements can go
|
|
9
|
+
directly to a pull request.
|
|
10
|
+
|
|
11
|
+
By participating, you agree to follow the [code of conduct](CODE_OF_CONDUCT.md).
|
|
12
|
+
Please report security vulnerabilities through the process in
|
|
13
|
+
[SECURITY.md](SECURITY.md), not through a public issue.
|
|
14
|
+
|
|
15
|
+
## Development
|
|
16
|
+
|
|
17
|
+
benchmatrix requires Python 3.11 or newer and uses
|
|
18
|
+
[uv](https://docs.astral.sh/uv/) for Python dependency management.
|
|
19
|
+
|
|
20
|
+
Set up and verify the development environment:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
make ready
|
|
24
|
+
make hooks-install
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Before submitting a change, run:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
make format
|
|
31
|
+
make check
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
For changes that may vary by interpreter or packaging environment, also run:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
make test-matrix
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This runs tests on Python 3.11 through 3.14 plus focused lint, type, dependency,
|
|
41
|
+
security, and release-artifact smoke sessions.
|
|
42
|
+
|
|
43
|
+
Documentation changes should pass `make docs`; API behavior changes should update
|
|
44
|
+
docstrings so the generated API reference stays current.
|
|
45
|
+
|
|
46
|
+
`make check` verifies the uv lockfile, Ruff formatting and linting, Markdown,
|
|
47
|
+
the documentation site, GitHub Actions workflows, CSpell, secret scanning,
|
|
48
|
+
Bandit, deptry, pip-audit, pytest and coverage, basedpyright, and built
|
|
49
|
+
distributions, including CycloneDX SBOM generation. New behavior should include
|
|
50
|
+
tests, and public APIs should include Google-style docstrings.
|
|
51
|
+
|
|
52
|
+
The Git hooks run fast, file-oriented checks. Use `make precommit` to run every
|
|
53
|
+
hook manually. Treat additions to `.secrets.baseline` as security-sensitive
|
|
54
|
+
changes and review each detected value before updating the baseline.
|
|
55
|
+
|
|
56
|
+
## Pull requests
|
|
57
|
+
|
|
58
|
+
Keep each pull request focused on one coherent change. In the description:
|
|
59
|
+
|
|
60
|
+
* explain the problem and the chosen approach;
|
|
61
|
+
* identify any public API or compatibility impact;
|
|
62
|
+
* include tests for behavior changes;
|
|
63
|
+
* update documentation and `CHANGELOG.md` when users will notice the change.
|
|
64
|
+
|
|
65
|
+
Maintainers may request changes before merging. Contributions are accepted
|
|
66
|
+
under the project's [MIT License](LICENSE).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ryan Wallace
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: benchmatrix
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: A pytest-benchmark matrix, metadata, and JSON results layer.
|
|
5
|
+
Project-URL: Homepage, https://github.com/ryancswallace/benchmatrix
|
|
6
|
+
Project-URL: Changelog, https://github.com/ryancswallace/benchmatrix/blob/main/CHANGELOG.md
|
|
7
|
+
Project-URL: Documentation, https://github.com/ryancswallace/benchmatrix#readme
|
|
8
|
+
Project-URL: Issues, https://github.com/ryancswallace/benchmatrix/issues
|
|
9
|
+
Project-URL: Source, https://github.com/ryancswallace/benchmatrix
|
|
10
|
+
Author-email: Ryan Wallace <ryancswallace@gmail.com>
|
|
11
|
+
Maintainer-email: Ryan Wallace <ryancswallace@gmail.com>
|
|
12
|
+
License-Expression: MIT
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Keywords: benchmark,benchmarking,performance,pytest,pytest-benchmark
|
|
15
|
+
Classifier: Development Status :: 3 - Alpha
|
|
16
|
+
Classifier: Framework :: Pytest
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
25
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
26
|
+
Classifier: Topic :: Software Development :: Testing
|
|
27
|
+
Requires-Python: <3.15,>=3.11
|
|
28
|
+
Requires-Dist: pytest-benchmark>=5.2.3
|
|
29
|
+
Requires-Dist: pytest>=9.1.1
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# benchmatrix
|
|
33
|
+
|
|
34
|
+
[](https://github.com/ryancswallace/benchmatrix/actions/workflows/ci.yml)
|
|
35
|
+
[](https://github.com/ryancswallace/benchmatrix/actions/workflows/docs.yml)
|
|
36
|
+
[](https://github.com/ryancswallace/benchmatrix/actions/workflows/docker.yml)
|
|
37
|
+
[](https://github.com/ryancswallace/benchmatrix/actions/workflows/codeql.yml)
|
|
38
|
+
[](https://github.com/ryancswallace/benchmatrix/actions/workflows/scorecard.yml)
|
|
39
|
+
[](https://github.com/ryancswallace/benchmatrix/actions/workflows/workflow-lint.yml)
|
|
40
|
+
[](https://github.com/ryancswallace/benchmatrix/blob/main/pyproject.toml)
|
|
41
|
+
[](https://github.com/DetachHead/basedpyright)
|
|
42
|
+
[](https://docs.astral.sh/ruff/)
|
|
43
|
+
[](https://github.com/ryancswallace/benchmatrix/blob/main/pyproject.toml)
|
|
44
|
+
[](https://cyclonedx.org/)
|
|
45
|
+
|
|
46
|
+
**Benchmark matrices for Python projects that need performance data they can
|
|
47
|
+
trust, compare, and parse.**
|
|
48
|
+
|
|
49
|
+
benchmatrix sits on top of
|
|
50
|
+
[pytest-benchmark](https://pytest-benchmark.readthedocs.io/) and adds the layer
|
|
51
|
+
that benchmark suites usually grow by hand: implementation-by-case matrices,
|
|
52
|
+
strict JSON-safe metadata, metric-aware result parsing, and concise display of
|
|
53
|
+
saved benchmark runs.
|
|
54
|
+
|
|
55
|
+
| Build repeatable suites | Keep metrics honest | Parse saved runs |
|
|
56
|
+
| --- | --- | --- |
|
|
57
|
+
| 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. |
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
Create a benchmark matrix from ordinary synchronous callables:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from benchmatrix import BenchmarkCase, make_benchmark_test
|
|
65
|
+
|
|
66
|
+
implementations = {
|
|
67
|
+
"builtin": sum,
|
|
68
|
+
"loop": lambda vs: sum(v for v in vs),
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
cases = [
|
|
72
|
+
BenchmarkCase.from_values(
|
|
73
|
+
"small",
|
|
74
|
+
list(range(100)),
|
|
75
|
+
work_units=100,
|
|
76
|
+
work_unit_name="items",
|
|
77
|
+
),
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
test_sum_matrix = make_benchmark_test(implementations, cases)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Run it with pytest-benchmark and keep the machine-readable output:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
uv run pytest tests/test_sum_benchmark.py --benchmark-json benchmark.json
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Read the tagged rows back later:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from benchmatrix import display_benchmark_rows, load_benchmark_json
|
|
93
|
+
|
|
94
|
+
rows = load_benchmark_json("benchmark.json")
|
|
95
|
+
display_benchmark_rows(rows)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Why It Exists
|
|
99
|
+
|
|
100
|
+
pytest-benchmark owns timing, calibration, statistics, terminal reporting, and
|
|
101
|
+
JSON export. benchmatrix owns the repeatable structure around those timings.
|
|
102
|
+
|
|
103
|
+
| Need | benchmatrix gives you |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| Compare multiple implementations | One generated pytest benchmark matrix instead of repeated parametrization code. |
|
|
106
|
+
| Track what each timing means | JSON-safe invocation metadata with implementation, case, and metric identity. |
|
|
107
|
+
| Report different metric views | Single-call latency, logical-work throughput, and local tail-latency summaries. |
|
|
108
|
+
| Reuse benchmark output | Parsers and display helpers for pytest-benchmark JSON produced by benchmatrix tests. |
|
|
109
|
+
|
|
110
|
+
benchmatrix is intentionally narrow: it benchmarks synchronous Python callables.
|
|
111
|
+
It is not a load-testing framework, production latency monitor, or replacement
|
|
112
|
+
for pytest-benchmark.
|
|
113
|
+
|
|
114
|
+
## Install
|
|
115
|
+
|
|
116
|
+
For local development from this repository:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
make ready
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
To try the package from another project before the first PyPI release, install
|
|
123
|
+
from GitHub:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
uv add "benchmatrix @ git+https://github.com/ryancswallace/benchmatrix"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Documentation
|
|
130
|
+
|
|
131
|
+
| Start here | Use it for |
|
|
132
|
+
| --- | --- |
|
|
133
|
+
| [First benchmark](docs/tutorials/first-benchmark.md) | A complete first benchmark from test file to parsed JSON. |
|
|
134
|
+
| [Create a benchmark matrix](docs/how-to/create-benchmark-matrix.md) | Cases, work units, fresh inputs, and synchronous target wrappers. |
|
|
135
|
+
| [Parse benchmark results](docs/how-to/parse-results.md) | Loading and displaying benchmatrix-tagged pytest-benchmark JSON. |
|
|
136
|
+
| [Performance model](docs/explanation/performance.md) | What the metrics mean and what they do not prove. |
|
|
137
|
+
| [Configuration and automation](docs/reference/configuration.md) | Make targets, CI workflows, Docker checks, docs, and SBOM generation. |
|
|
138
|
+
|
|
139
|
+
The MkDocs site builds in strict mode and generates API reference pages from the
|
|
140
|
+
package docstrings.
|
|
141
|
+
|
|
142
|
+
## Project Links
|
|
143
|
+
|
|
144
|
+
* [Examples](examples/)
|
|
145
|
+
* [Contributing](CONTRIBUTING.md)
|
|
146
|
+
* [Changelog](CHANGELOG.md)
|
|
147
|
+
* [Security policy](SECURITY.md)
|
|
148
|
+
* [Release policy](RELEASING.md)
|
|
149
|
+
* [Code of conduct](CODE_OF_CONDUCT.md)
|
|
150
|
+
* [Citation metadata](CITATION.cff)
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
benchmatrix is distributed under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# benchmatrix
|
|
2
|
+
|
|
3
|
+
[](https://github.com/ryancswallace/benchmatrix/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/ryancswallace/benchmatrix/actions/workflows/docs.yml)
|
|
5
|
+
[](https://github.com/ryancswallace/benchmatrix/actions/workflows/docker.yml)
|
|
6
|
+
[](https://github.com/ryancswallace/benchmatrix/actions/workflows/codeql.yml)
|
|
7
|
+
[](https://github.com/ryancswallace/benchmatrix/actions/workflows/scorecard.yml)
|
|
8
|
+
[](https://github.com/ryancswallace/benchmatrix/actions/workflows/workflow-lint.yml)
|
|
9
|
+
[](https://github.com/ryancswallace/benchmatrix/blob/main/pyproject.toml)
|
|
10
|
+
[](https://github.com/DetachHead/basedpyright)
|
|
11
|
+
[](https://docs.astral.sh/ruff/)
|
|
12
|
+
[](https://github.com/ryancswallace/benchmatrix/blob/main/pyproject.toml)
|
|
13
|
+
[](https://cyclonedx.org/)
|
|
14
|
+
|
|
15
|
+
**Benchmark matrices for Python projects that need performance data they can
|
|
16
|
+
trust, compare, and parse.**
|
|
17
|
+
|
|
18
|
+
benchmatrix sits on top of
|
|
19
|
+
[pytest-benchmark](https://pytest-benchmark.readthedocs.io/) and adds the layer
|
|
20
|
+
that benchmark suites usually grow by hand: implementation-by-case matrices,
|
|
21
|
+
strict JSON-safe metadata, metric-aware result parsing, and concise display of
|
|
22
|
+
saved benchmark runs.
|
|
23
|
+
|
|
24
|
+
| Build repeatable suites | Keep metrics honest | Parse saved runs |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| 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. |
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
Create a benchmark matrix from ordinary synchronous callables:
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from benchmatrix import BenchmarkCase, make_benchmark_test
|
|
34
|
+
|
|
35
|
+
implementations = {
|
|
36
|
+
"builtin": sum,
|
|
37
|
+
"loop": lambda vs: sum(v for v in vs),
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
cases = [
|
|
41
|
+
BenchmarkCase.from_values(
|
|
42
|
+
"small",
|
|
43
|
+
list(range(100)),
|
|
44
|
+
work_units=100,
|
|
45
|
+
work_unit_name="items",
|
|
46
|
+
),
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
test_sum_matrix = make_benchmark_test(implementations, cases)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Run it with pytest-benchmark and keep the machine-readable output:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
uv run pytest tests/test_sum_benchmark.py --benchmark-json benchmark.json
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Read the tagged rows back later:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from benchmatrix import display_benchmark_rows, load_benchmark_json
|
|
62
|
+
|
|
63
|
+
rows = load_benchmark_json("benchmark.json")
|
|
64
|
+
display_benchmark_rows(rows)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Why It Exists
|
|
68
|
+
|
|
69
|
+
pytest-benchmark owns timing, calibration, statistics, terminal reporting, and
|
|
70
|
+
JSON export. benchmatrix owns the repeatable structure around those timings.
|
|
71
|
+
|
|
72
|
+
| Need | benchmatrix gives you |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| Compare multiple implementations | One generated pytest benchmark matrix instead of repeated parametrization code. |
|
|
75
|
+
| Track what each timing means | JSON-safe invocation metadata with implementation, case, and metric identity. |
|
|
76
|
+
| Report different metric views | Single-call latency, logical-work throughput, and local tail-latency summaries. |
|
|
77
|
+
| Reuse benchmark output | Parsers and display helpers for pytest-benchmark JSON produced by benchmatrix tests. |
|
|
78
|
+
|
|
79
|
+
benchmatrix is intentionally narrow: it benchmarks synchronous Python callables.
|
|
80
|
+
It is not a load-testing framework, production latency monitor, or replacement
|
|
81
|
+
for pytest-benchmark.
|
|
82
|
+
|
|
83
|
+
## Install
|
|
84
|
+
|
|
85
|
+
For local development from this repository:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
make ready
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
To try the package from another project before the first PyPI release, install
|
|
92
|
+
from GitHub:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
uv add "benchmatrix @ git+https://github.com/ryancswallace/benchmatrix"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Documentation
|
|
99
|
+
|
|
100
|
+
| Start here | Use it for |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| [First benchmark](docs/tutorials/first-benchmark.md) | A complete first benchmark from test file to parsed JSON. |
|
|
103
|
+
| [Create a benchmark matrix](docs/how-to/create-benchmark-matrix.md) | Cases, work units, fresh inputs, and synchronous target wrappers. |
|
|
104
|
+
| [Parse benchmark results](docs/how-to/parse-results.md) | Loading and displaying benchmatrix-tagged pytest-benchmark JSON. |
|
|
105
|
+
| [Performance model](docs/explanation/performance.md) | What the metrics mean and what they do not prove. |
|
|
106
|
+
| [Configuration and automation](docs/reference/configuration.md) | Make targets, CI workflows, Docker checks, docs, and SBOM generation. |
|
|
107
|
+
|
|
108
|
+
The MkDocs site builds in strict mode and generates API reference pages from the
|
|
109
|
+
package docstrings.
|
|
110
|
+
|
|
111
|
+
## Project Links
|
|
112
|
+
|
|
113
|
+
* [Examples](examples/)
|
|
114
|
+
* [Contributing](CONTRIBUTING.md)
|
|
115
|
+
* [Changelog](CHANGELOG.md)
|
|
116
|
+
* [Security policy](SECURITY.md)
|
|
117
|
+
* [Release policy](RELEASING.md)
|
|
118
|
+
* [Code of conduct](CODE_OF_CONDUCT.md)
|
|
119
|
+
* [Citation metadata](CITATION.cff)
|
|
120
|
+
|
|
121
|
+
## License
|
|
122
|
+
|
|
123
|
+
benchmatrix is distributed under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Release policy
|
|
2
|
+
|
|
3
|
+
benchmatrix uses [Semantic Versioning](https://semver.org/).
|
|
4
|
+
|
|
5
|
+
## Compatibility
|
|
6
|
+
|
|
7
|
+
While the project is pre-1.0:
|
|
8
|
+
|
|
9
|
+
* patch releases contain compatible fixes and documentation improvements;
|
|
10
|
+
* minor releases may introduce breaking API changes;
|
|
11
|
+
* breaking changes should be called out clearly in the changelog.
|
|
12
|
+
|
|
13
|
+
Starting with 1.0, incompatible public API changes require a major release.
|
|
14
|
+
The supported public API is the set of names exported from
|
|
15
|
+
`benchmatrix.__init__`. Private modules and names beginning with an underscore
|
|
16
|
+
are not covered by the compatibility guarantee.
|
|
17
|
+
|
|
18
|
+
Python version support may change in a minor release before 1.0 and in a major
|
|
19
|
+
release after 1.0. Dropping a Python version will be documented in advance when
|
|
20
|
+
practical.
|
|
21
|
+
|
|
22
|
+
Release branches are not maintained as standing support branches. The active
|
|
23
|
+
support branch is `main`; temporary release or security branches may be used for
|
|
24
|
+
coordination and retired after release.
|
|
25
|
+
|
|
26
|
+
## Release process
|
|
27
|
+
|
|
28
|
+
Releases are prepared in a normal pull request and published by the GitHub
|
|
29
|
+
Actions release workflow after a GitHub Release is published.
|
|
30
|
+
|
|
31
|
+
1. Choose the next version from the changelog and compatibility policy.
|
|
32
|
+
2. Update release metadata:
|
|
33
|
+
|
|
34
|
+
* set `project.version` in `pyproject.toml`;
|
|
35
|
+
* set `version` in `CITATION.cff`;
|
|
36
|
+
* add or update `date-released` in `CITATION.cff` once the release date is
|
|
37
|
+
known.
|
|
38
|
+
|
|
39
|
+
3. Move user-visible `CHANGELOG.md` entries from `Unreleased` into a versioned
|
|
40
|
+
section such as `## 0.2.0 - 2026-06-20`, then leave a fresh `Unreleased`
|
|
41
|
+
section at the top.
|
|
42
|
+
4. Run the release validation commands:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
make check-all
|
|
46
|
+
make build
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
5. Confirm `dist/` contains one source distribution, one wheel, and
|
|
50
|
+
`benchmatrix.cdx.json` for the intended version.
|
|
51
|
+
6. Merge the release pull request after required checks pass.
|
|
52
|
+
7. Create and push an annotated tag named `vX.Y.Z` for the release commit.
|
|
53
|
+
8. Draft GitHub release notes from the changelog section for that version.
|
|
54
|
+
9. Publish the GitHub Release. Publishing the release triggers
|
|
55
|
+
`.github/workflows/release.yml`, which rebuilds artifacts, attests them, and
|
|
56
|
+
publishes to PyPI through Trusted Publishing.
|
|
57
|
+
10. Verify the package from PyPI in a clean environment.
|
|
58
|
+
11. If any post-release fix is needed, prepare a new patch release. Do not
|
|
59
|
+
replace files for an already-published PyPI version.
|
|
60
|
+
|
|
61
|
+
The detailed operational checklist lives in `docs/runbooks/release.md`.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Security fixes are provided for the latest released version of benchmatrix.
|
|
6
|
+
Because the project is currently pre-1.0, fixes are not routinely backported to
|
|
7
|
+
older minor versions.
|
|
8
|
+
|
|
9
|
+
The active support branch is `main`. Temporary security release branches may be
|
|
10
|
+
created for coordinated disclosure, but they are not maintained after the fix is
|
|
11
|
+
released unless the release notes explicitly say otherwise.
|
|
12
|
+
|
|
13
|
+
A backport to an older release may be considered when the issue is high impact,
|
|
14
|
+
the patch is small and safe, the affected release still has meaningful user
|
|
15
|
+
adoption, and the maintainer has capacity to validate and publish the backport.
|
|
16
|
+
|
|
17
|
+
## Reporting a vulnerability
|
|
18
|
+
|
|
19
|
+
Please do not open a public issue for a suspected vulnerability.
|
|
20
|
+
|
|
21
|
+
Email Ryan Wallace at <ryancswallace@gmail.com> with:
|
|
22
|
+
|
|
23
|
+
* the affected version;
|
|
24
|
+
* steps to reproduce the issue;
|
|
25
|
+
* the potential impact;
|
|
26
|
+
* any suggested mitigation, if known.
|
|
27
|
+
|
|
28
|
+
You should receive an acknowledgement within seven days. The maintainer will
|
|
29
|
+
coordinate validation, remediation, and disclosure with the reporter. Please
|
|
30
|
+
allow a reasonable period for a fix before publishing details.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Generate mkdocstrings API reference pages for benchmatrix modules."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import mkdocs_gen_files
|
|
6
|
+
|
|
7
|
+
PACKAGE_ROOT = Path("src/benchmatrix")
|
|
8
|
+
REFERENCE_ROOT = Path("reference/api")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _iter_public_modules() -> list[tuple[str, Path, Path]]:
|
|
12
|
+
"""Return import path, source path, and generated docs path tuples."""
|
|
13
|
+
modules: list[tuple[str, Path, Path]] = []
|
|
14
|
+
for source_path in sorted(PACKAGE_ROOT.glob("*.py")):
|
|
15
|
+
if source_path.name.startswith("_") and source_path.name != "__init__.py":
|
|
16
|
+
continue
|
|
17
|
+
|
|
18
|
+
module_parts = source_path.relative_to("src").with_suffix("").parts
|
|
19
|
+
import_path = ".".join(part for part in module_parts if part != "__init__")
|
|
20
|
+
if source_path.name == "__init__.py":
|
|
21
|
+
docs_path = REFERENCE_ROOT / "index.md"
|
|
22
|
+
else:
|
|
23
|
+
docs_path = REFERENCE_ROOT / f"{source_path.stem}.md"
|
|
24
|
+
modules.append((import_path, source_path, docs_path))
|
|
25
|
+
return modules
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
for module, source, docs_path in _iter_public_modules():
|
|
29
|
+
title = "benchmatrix" if module == "benchmatrix" else module.rsplit(".", 1)[-1].replace("_", " ").title()
|
|
30
|
+
with mkdocs_gen_files.open(docs_path, "w") as output:
|
|
31
|
+
output.write(f"# {title}\n\n")
|
|
32
|
+
output.write(f"::: {module}\n")
|
|
33
|
+
|
|
34
|
+
mkdocs_gen_files.set_edit_path(docs_path, source)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
The repository changelog is the source of truth for release notes.
|
|
4
|
+
|
|
5
|
+
For each user-visible change:
|
|
6
|
+
|
|
7
|
+
1. add an entry under `Unreleased` in `CHANGELOG.md`;
|
|
8
|
+
2. group the entry under the appropriate heading;
|
|
9
|
+
3. mention compatibility or migration notes when behavior changes;
|
|
10
|
+
4. move entries into a versioned section during release preparation.
|
|
11
|
+
|
|
12
|
+
The project follows Semantic Versioning with the pre-1.0 expectations described
|
|
13
|
+
in the release policy.
|