Lightweight Python microbenchmarking library with Rust core (PyO3)
Project description
blackbox-bench
A lightweight Python microbenchmarking library with a Rust core (PyO3 + maturin). Designed as a "criterion for Python" — minimal harness overhead, statistically rigorous output, and a small CLI that drops into CI.
import blackbox_bench
bench = blackbox_bench.Bench()
@bench.benchmark
def hash_1kb():
import hashlib
hashlib.sha256(b"x" * 1024).digest()
bench.run()
bench.report() # human-readable table
bench.report(format="json", path="results.json")
blackbox-bench results
─────────────────────────────────────────────────────────────────────────────────
Name Mean Median StdDev Min Max Ops/sec CI 95% Outliers
─────────────────────────────────────────────────────────────────────────────────
hash_1kb 1.4 µs 1.4 µs 12.0 ns 1.4 µs 1.5 µs 710,221 [1.4 µs, 1.4 µs] 3
─────────────────────────────────────────────────────────────────────────────────
Features
- Per-batch timing with auto-batch-sizing — sub-microsecond functions are batched until each sample takes ≥5 µs, well above the timer resolution floor.
- Per-iteration overhead measurement and subtraction — the harness probes itself at startup so reported nanoseconds attribute time to your code, not blackbox-bench.
- Bootstrap 95% confidence intervals for the mean, plus Tukey or MAD outlier detection.
blackbox_bench.black_box(value)— opaque pass-through that the optimiser can't see through.bench.iter_batched(setup, routine)— setup runs once per sample (untimed); routine runs the timed batch.throughput=—@bench.benchmark(throughput=1024)reports MB/s alongside ops/sec.params=[...]— parameterised benchmarks; one result per parameter.- Opt-in HDR histograms —
Bench(histogram=True)attaches a percentile-queryableHdrHistogramto each result. blackbox_bench.compare(baseline_json, current_json)— classifies each row asunchanged/regressed/improved/new/removedusing CI overlap, not rawchange_pct.- Four reporters — table, JSON, self-contained HTML (with inline SVG sparklines), JUnit-compatible XML (with a raw alternative).
blackbox-bench run --profile— wraps each benchmark inpy-spyand emits SVG flamegraphs alongside the results.
Install
pip install blackbox-bench
Pre-built abi3 wheels are published for cpython 3.10 / 3.11 / 3.12 / 3.13 on linux (x86_64 + aarch64), macOS (x86_64 + aarch64), and windows x86_64. Building from source requires a Rust toolchain.
Optional extras:
pip install blackbox-bench[profile] # adds py-spy for `blackbox-bench run --profile`
Usage
Decorator API
import blackbox_bench
bench = blackbox_bench.Bench(
warmup=5,
target_time_ns=1_000_000_000,
outlier_method="tukey", # or "mad" / "none"
overhead_subtract=True,
histogram=False,
)
@bench.benchmark
def quick(): sum(range(100))
@bench.benchmark(name="hash_kb", throughput=1024, params=[10, 100, 1000])
def hashing(n):
import hashlib
hashlib.sha256(b"x" * n).digest()
results = bench.run()
bench.report(format="html", path="results.html")
iter_batched for setup-isolated timing
import random
@bench.benchmark
def sort_random():
return bench.iter_batched(
setup=lambda: random.sample(range(1_000), 1_000),
routine=lambda xs: sorted(xs),
)
setup runs once per sample and isn't timed; routine is the timed call inside the batch.
Context manager
with bench.measure("payload_build"):
payload = build_huge_payload()
bench.run() # appends measured contexts to results
Module-level decorator + CLI
# bench_hashing.py
import blackbox_bench
@blackbox_bench.benchmark
def sha256_1kb():
import hashlib
hashlib.sha256(b"x" * 1024).digest()
blackbox-bench run bench_hashing.py --warmup 5 --iterations 100
blackbox-bench run benches/ --format html --output report.html
blackbox-bench run benches/ --save baseline.json
blackbox-bench compare baseline.json current.json # CI-classified diff
Comparing runs
import json
report = blackbox_bench.compare(
open("baseline.json").read(),
open("current.json").read(),
)
for row in report.rows:
print(row.name, row.classification, row.change_pct)
ComparisonReport.format("xml") emits JUnit with <failure> on regressed rows — drop the file into Jenkins/GitHub Actions test reporters.
Why Rust under the hood
The harness has to stay small relative to the user's function:
- Tight sampling loop —
Instant::now()and the per-batch call dispatch are raw FFI (PyObject_CallNoArgs/PyObject_CallObject), skipping PyO3's higher-level wrappers inside the timed window. - GIL released during stats — bootstrap CI, Tukey/MAD, and the histogram run inside
py.detach(...)so other Python threads aren't blocked while blackbox-bench crunches its samples. - Reused scratch buffers —
median,tukey,mad, andbootstrap_ci_meanshare twoVecs owned by theRunner; a 100-benchmark suite still allocates only once for the lot.
The criterion benchmarks at benches/rust_internals.rs measure these primitives directly. benches/bench_dogfood.py measures the assembled harness end-to-end (the empty-pass benchmark should report ~0–1 ns after overhead subtraction).
Migrating from 0.1.0
See MIGRATION.md. Most v0.1.0 code only needs an import swap; the one surface that changed without alias is Bench.report(json_output=True) → Bench.report(format="json"). For exact v0.1.0 semantics:
from blackbox_bench.legacy import Bench, benchmark, BenchmarkResult
The legacy shim is removed in v1.1.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file blackbox_bench-1.0.0-cp310-abi3-win_amd64.whl.
File metadata
- Download URL: blackbox_bench-1.0.0-cp310-abi3-win_amd64.whl
- Upload date:
- Size: 224.2 kB
- Tags: CPython 3.10+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e9a2b42fe54961b17481748bd926f97ebba42e6a4fe65a7f7fa5a0ee9fef5a0
|
|
| MD5 |
514b6bd994d24123936a81568ff2703d
|
|
| BLAKE2b-256 |
8f9f72c58bbf22c8e7ffa668ed7232396b58297ead66fc6903314eb12e6a108f
|
Provenance
The following attestation bundles were made for blackbox_bench-1.0.0-cp310-abi3-win_amd64.whl:
Publisher:
release.yml on quinnjr/blackbox-bench
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
blackbox_bench-1.0.0-cp310-abi3-win_amd64.whl -
Subject digest:
0e9a2b42fe54961b17481748bd926f97ebba42e6a4fe65a7f7fa5a0ee9fef5a0 - Sigstore transparency entry: 1585748952
- Sigstore integration time:
-
Permalink:
quinnjr/blackbox-bench@a766cf34782af9a86df7a9505a7b027e639714f8 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/quinnjr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a766cf34782af9a86df7a9505a7b027e639714f8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file blackbox_bench-1.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: blackbox_bench-1.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 310.7 kB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79b589e8f81588c792be290d4b73b9ea9434595706a409ce779096597f8a14ab
|
|
| MD5 |
537f2cc8b529678010ce9b0620dc586e
|
|
| BLAKE2b-256 |
9618a07c2022bbaccf920ca5e8d33e05676f626bd6fe1360082a1a648a3f492d
|
Provenance
The following attestation bundles were made for blackbox_bench-1.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on quinnjr/blackbox-bench
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
blackbox_bench-1.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
79b589e8f81588c792be290d4b73b9ea9434595706a409ce779096597f8a14ab - Sigstore transparency entry: 1585749061
- Sigstore integration time:
-
Permalink:
quinnjr/blackbox-bench@a766cf34782af9a86df7a9505a7b027e639714f8 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/quinnjr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a766cf34782af9a86df7a9505a7b027e639714f8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file blackbox_bench-1.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: blackbox_bench-1.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 298.0 kB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0ba40766f35432cfdbb0ef7f36aa56341a2fcfd36b1ff67a2acadc48da013840
|
|
| MD5 |
2b922f0ff7f4e499359fa72fabd03c22
|
|
| BLAKE2b-256 |
bc8e0805b0eda8b31d23139d2e45450171fa1e38d5978175c375b6af57626a96
|
Provenance
The following attestation bundles were made for blackbox_bench-1.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on quinnjr/blackbox-bench
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
blackbox_bench-1.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
0ba40766f35432cfdbb0ef7f36aa56341a2fcfd36b1ff67a2acadc48da013840 - Sigstore transparency entry: 1585749155
- Sigstore integration time:
-
Permalink:
quinnjr/blackbox-bench@a766cf34782af9a86df7a9505a7b027e639714f8 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/quinnjr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a766cf34782af9a86df7a9505a7b027e639714f8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file blackbox_bench-1.0.0-cp310-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: blackbox_bench-1.0.0-cp310-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 280.4 kB
- Tags: CPython 3.10+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
62f5827959b3e0bf63804a5802c5f5090e71c86c703af96cd7fde303040d1119
|
|
| MD5 |
4ec53c36b7bbe259f59ee624eb3ea05d
|
|
| BLAKE2b-256 |
341d97dd7da9d43d7351265e138ad21607029163247a13dd5dd723eb655afd0c
|
Provenance
The following attestation bundles were made for blackbox_bench-1.0.0-cp310-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on quinnjr/blackbox-bench
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
blackbox_bench-1.0.0-cp310-abi3-macosx_11_0_arm64.whl -
Subject digest:
62f5827959b3e0bf63804a5802c5f5090e71c86c703af96cd7fde303040d1119 - Sigstore transparency entry: 1585749263
- Sigstore integration time:
-
Permalink:
quinnjr/blackbox-bench@a766cf34782af9a86df7a9505a7b027e639714f8 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/quinnjr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a766cf34782af9a86df7a9505a7b027e639714f8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file blackbox_bench-1.0.0-cp310-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: blackbox_bench-1.0.0-cp310-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 292.8 kB
- Tags: CPython 3.10+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fda519baaf672c42c98857232f1527385f00c3aec300d2686a178f630fc197a4
|
|
| MD5 |
a13404e8c9709c6f60a66ed60d19acaf
|
|
| BLAKE2b-256 |
f1861f6421492e0ce6a50e37a3738efcb170033bb114ea69a6b4a1f08a710426
|
Provenance
The following attestation bundles were made for blackbox_bench-1.0.0-cp310-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on quinnjr/blackbox-bench
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
blackbox_bench-1.0.0-cp310-abi3-macosx_10_12_x86_64.whl -
Subject digest:
fda519baaf672c42c98857232f1527385f00c3aec300d2686a178f630fc197a4 - Sigstore transparency entry: 1585749366
- Sigstore integration time:
-
Permalink:
quinnjr/blackbox-bench@a766cf34782af9a86df7a9505a7b027e639714f8 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/quinnjr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a766cf34782af9a86df7a9505a7b027e639714f8 -
Trigger Event:
push
-
Statement type: