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)

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 converts them to microseconds only for display. Benchmark values vary between machines and even between runs on the same machine; compare results only under controlled conditions.

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.2.0.tar.gz (6.1 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.2.0-py3-none-any.whl (8.2 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for benchcore-0.2.0.tar.gz
Algorithm Hash digest
SHA256 74170604d4df422b0e5504a7eb8e6a6444a25c016bda9cfaad99bb9c0e760ef7
MD5 2a628b2270e5b867b74f8ff40852c44c
BLAKE2b-256 a545e522fc70291c2d51bc357b00ffb238f497d0e3a24fc08d68ccaa06bb9a14

See more details on using hashes here.

Provenance

The following attestation bundles were made for benchcore-0.2.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.2.0-py3-none-any.whl.

File metadata

  • Download URL: benchcore-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 8.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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 65849b4ea8786689c8f8b01898eee49ae76704d09e499118cd07985830760b22
MD5 03069b315ec103ff2ec0e083f6819df8
BLAKE2b-256 ae98fcc2f32ea281c8692c39e840aa2be780b2dcf1224f5ab1a8dfd079c6c533

See more details on using hashes here.

Provenance

The following attestation bundles were made for benchcore-0.2.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

0.3.0

2 files

This release

0.2.0 This release

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