Skip to main content

BenchCore

[!IMPORTANT] BenchCore is pre-alpha. A minimal benchmarking API exists for experimentation, but it is not ready for production use and may change without notice.

BenchCore is a strongly typed, framework-agnostic benchmarking engine for Python. Its goal is to provide the measurement primitives needed by test framework integrations without making the core depend on any test runner.

The project grew out of a desire for a benchmarking codebase where typing, maintainability, and ease of contribution are foundational constraints. Existing tools such as pytest-benchmark helped demonstrate the value of benchmarking in developer workflows. BenchCore is an independent implementation with a broader architectural goal: a reusable engine that can eventually serve pytest, unittest, and other integrations.

BenchCore is not a testing framework, a test runner, or a drop-in replacement for pytest-benchmark. It will measure code; the surrounding framework will remain responsible for discovering and running tests.

Design goals

  • A small, stable, and strongly typed public API.
  • Strict Pyright compatibility without exposing Any in public interfaces.
  • No runtime dependency on pytest or another testing framework.
  • Replaceable timers, calibration, statistics, reporting, and storage components.
  • Near-zero runtime dependencies and low measurement overhead.
  • An approachable codebase designed for long-term maintenance.
  • Support for Python 3.12 and newer.

These are design constraints, not claims about features already implemented.

Intended experience

The eventual standalone API should be simple enough to look like this:

from benchcore import Bench

bench = Bench()
result = bench.run(sorted, [5, 4, 3, 2, 1])

print(result.statistics.mean_ns)

Or, for the common case:

from benchcore import benchmark

result = benchmark(sorted, [5, 4, 3, 2, 1])

Both examples are implemented by the current MVP. Configuration is available through Bench:

from benchcore import Bench, BenchmarkConfig

bench = Bench(BenchmarkConfig(rounds=20, warmup_rounds=2))
result = bench.run(sorted, [5, 4, 3, 2, 1])

By default, BenchCore calibrates the iteration count until a round reaches a target duration. Calibration samples are discarded before warmup and measurement:

config = BenchmarkConfig(
    target_round_time_ns=10_000_000,
    max_iterations=1_000_000,
    max_calibration_time_ns=1_000_000_000,
)
result = Bench(config).run(sorted, [5, 4, 3, 2, 1])

print(result.iterations)

Set iterations explicitly to disable calibration when a fixed count is required:

config = BenchmarkConfig(iterations=100)

max_calibration_time_ns is an accumulated calibration budget, not a hard timeout. BenchCore cannot interrupt a running callable, so one slow invocation may exceed the budget before calibration stops.

Fixed iterations are preferable when repeated calls change workload cost, mutate shared state, consume a finite input, or when reproducing an earlier run with an exact count. Automatic calibration is intended for callables whose cost remains reasonably stable across repeated invocations.

Running the example

Install the development environment and execute the standalone example:

poetry install
poetry run python examples/basic.py

The reported durations are normalized per iteration and stored in nanoseconds. The example uses format_duration_ns() to select a readable display unit without changing the stored numeric data. Benchmark values vary between machines and even between runs on the same machine; compare results only under controlled conditions.

Results and units

Duration-bearing names include their unit explicitly. Whole measured regions use integer nanoseconds; normalized durations and statistics use floats because one iteration may represent a fraction of a timer tick:

from benchcore import format_duration_ns

print(result.total_time_ns)
print(result.statistics.mean_ns)
print(format_duration_ns(result.statistics.mean_ns))

standard_deviation_ns is the sample standard deviation across measured rounds. It uses Bessel's correction and is 0.0 when only one round exists. These descriptive statistics summarize observed runtime noise; they do not establish statistical significance or prove that one implementation is faster.

Quartiles, percentiles, and outlier labels are intentionally deferred until BenchCore defines minimum sample sizes and interpolation policies.

Scope

The core is expected to grow around a small number of benchmarking concepts:

  • precise and replaceable timers;
  • warmup and calibration;
  • iterations and rounds;
  • immutable results and descriptive statistics;
  • reporters and result storage;
  • regression comparison;
  • isolated adapters for testing frameworks.

Features will be designed only when there is a concrete use case. BenchCore will prefer composition and small protocols over speculative abstraction.

Project status

BenchCore is currently pre-alpha. The development version supports explicit rounds, automatic or fixed iterations, warmups, an injectable nanosecond timer, and basic descriptive statistics. Async callables, reporters, storage, framework integrations, and stability guarantees have not been implemented.

No compatibility guarantees apply until an initial public release. Once public APIs exist, changes will be documented in CHANGELOG.md.

Contributing

Early contributions are especially valuable when they clarify use cases and API constraints. Before implementing a substantial feature, please open an issue so the design and trade-offs can be discussed first. See CONTRIBUTING.md for the complete process.

By participating, you agree to follow the Code of Conduct. Please report security issues privately as described in SECURITY.md.

License

BenchCore is distributed under the terms in LICENSE.md.

Download files

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

Source Distribution

benchcore-0.3.0.tar.gz (6.8 kB view details)

Uploaded Source

Built Distribution

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

benchcore-0.3.0-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

File details

Details for the file benchcore-0.3.0.tar.gz.

File metadata

  • Download URL: benchcore-0.3.0.tar.gz
  • Upload date:
  • Size: 6.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for benchcore-0.3.0.tar.gz
Algorithm Hash digest
SHA256 27151a8cdf8c3425edf291144cdc3aa95707defe307fdc4247b365bbf0a7c91c
MD5 ec7845fc13dfc22ea3e817bc61ccf357
BLAKE2b-256 5da7ad644ab26f578127bcd7b5778bb54ece1e715ec9b62a9c71c10d54829610

See more details on using hashes here.

Provenance

The following attestation bundles were made for benchcore-0.3.0.tar.gz:

Publisher: publish.yml on ezer-mackenzie/benchcore

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

File details

Details for the file benchcore-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: benchcore-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 9.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for benchcore-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3c722722b51d381ffd9e5be78d84ce7b7c32b0b36054d32810dc2481f40b66d5
MD5 db6dd7da36e60b4acdffafcab72e2e89
BLAKE2b-256 54159cdfd53394c954df10e36549db7c5fa597441eda66de4654ebaa710fa649

See more details on using hashes here.

Provenance

The following attestation bundles were made for benchcore-0.3.0-py3-none-any.whl:

Publisher: publish.yml on ezer-mackenzie/benchcore

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.0.0

2 files

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

This release

0.3.0 This release

2 files

0.2.0

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