Skip to main content

Simple and fast benchmarking utilities for Python functions

Project description

bencheetah

Simple, zero-dependency benchmarking utilities for Python functions — now with scaling experiments and charts.

PyPI version Python License: MIT CI

Open In Colab


Why bencheetah?

timeit is verbose. cProfile is overkill for quick comparisons. bencheetah gives you:

  • Statistical timing (mean, min, max, stdev) for a single function.
  • Side-by-side comparison of multiple implementations.
  • Scaling experiments: sweep a range of input sizes and plot execution time vs. n — ideal for empirically verifying algorithmic complexity.
  • Beautiful terminal tables and matplotlib charts with a single call.

No dependencies for the core functions. matplotlib only needed for plotting.


Installation

# Core (no dependencies)
pip install bencheetah

# With plotting support
pip install "bencheetah[plot]"

Requires Python ≥ 3.10.


Quick Start

Benchmark a single function

from bencheetah import benchmark, format_results

result = benchmark(sum, range(1_000_000), repeats=10)
print(format_results(result))
┌──────────────────────────────────────────┐
│   bencheetah — sum                     │
├──────────────────────────────────────────┤
│  Runs                                10  │
│  Mean                           8.23 ms  │
│  Min                            7.91 ms  │
│  Max                            9.14 ms  │
│  Total                         82.32 ms  │
└──────────────────────────────────────────┘

Compare multiple implementations

from bencheetah import compare, format_results

def loop_sum(n):
    return sum(range(n))

def gauss_sum(n):
    return n * (n - 1) // 2

out = compare(
    {"loop": loop_sum, "gauss": gauss_sum},
    args=(1_000_000,),
    repeats=8,
)
print(format_results(out))
 bencheetah — comparison (2 functions)
────────────────────────────────────────────────────────────
  Function            Mean          Min          Max         Total
────────────────────────────────────────────────────────────
  gauss W        142.00 ns    130.00 ns    180.00 ns    1.14 µs
  loop              8.23 ms      7.91 ms      9.14 ms   65.84 ms   (57930.8x slower)
────────────────────────────────────────────────────────────

  Winner: gauss W

Scaling experiment (execution time vs input size)

from bencheetah import scale_benchmark, plot_scaling

def bubble_sort(lst):
    lst = lst[:]
    n = len(lst)
    for i in range(n):
        for j in range(n - i - 1):
            if lst[j] > lst[j + 1]:
                lst[j], lst[j + 1] = lst[j + 1], lst[j]
    return lst

data = scale_benchmark(
    funcs={
        "sorted() built-in": sorted,
        "bubble sort":       bubble_sort,
    },
    input_gen=lambda n: list(range(n, 0, -1)),  # worst-case: reversed list
    sizes=[100, 500, 1_000, 2_000, 5_000],
    repeats=5,
)

fig, ax = plot_scaling(data, title="Sort algorithm scaling")

The chart shows mean execution time (±1 stdev error bars) vs input size, one line per algorithm — perfect for comparing O(n log n) vs O(n²) empirically.


API Reference

benchmark(func, *args, repeats=5, warmup=1, **kwargs) → dict

Runs func(*args, **kwargs) multiple times and returns timing statistics.

Key Description
name Function name
runs Number of timed runs
mean Average execution time (seconds)
min Fastest run
max Slowest run
stdev Standard deviation
total Sum of all runs

Parameters:

  • func — Callable to benchmark.
  • *args — Positional arguments forwarded to func.
  • repeats (int) — Number of timed runs. Default: 5.
  • warmup (int) — Un-timed warm-up runs (avoids cold-start effects). Default: 1.
  • **kwargs — Keyword arguments forwarded to func.

compare(funcs, args=None, kwargs=None, repeats=5, warmup=1) → dict

Benchmarks multiple functions with the same inputs and ranks them by mean time.

Key Description
results Dict of benchmark dicts keyed by label
winner Label of the fastest function
ranking List of {name, mean} sorted fastest → slowest

Parameters:

  • funcs (dict){"label": callable, ...}.
  • args (tuple) — Positional arguments shared by all functions.
  • kwargs (dict) — Keyword arguments shared by all functions.
  • repeats, warmup — Same as benchmark.

scale_benchmark(funcs, input_gen, sizes, repeats=5, warmup=1) → dict

Runs a scaling experiment: benchmarks one or more functions across a range of input sizes.

Parameters:

  • funcs — A single callable or a {"label": callable} dict.
  • input_gen (callable) — Receives an integer n and returns the input for that size. Return a tuple if the function needs multiple positional arguments.
    input_gen = lambda n: list(range(n))          # single arg
    input_gen = lambda n: (list(range(n)), True)  # multiple args → unpacked
    
  • sizes (iterable[int]) — The input sizes to sweep, e.g. [100, 1000, 5000, 10_000].
  • repeats, warmup — Same as benchmark.

Returns a dict keyed by function label, each value containing: {"sizes": [...], "means": [...], "stdevs": [...], "mins": [...], "maxs": [...]}.


plot_scaling(scale_data, *, ...) → (Figure, Axes)

Plots the output of scale_benchmark() as a line chart (mean time vs input size).

Requires matplotlib. Install with pip install "bencheetah[plot]".

Parameter Default Description
title "Execution time vs input size" Chart title
xlabel "Input size (n)" X-axis label
ylabel auto Y-axis label (auto-generated from time unit)
time_unit "auto" One of "auto", "s", "ms", "us", "ns"
show_errorbars True Draw ±1 stdev error bars
show_minmax_band False Shade the min–max range behind each line
logscale False Logarithmic Y axis
figsize (9, 5) Matplotlib figure size in inches
save_path None Save to file (.png, .svg, .pdf, …)
show True Call plt.show()

format_results(data) → str

Formats the output of benchmark() or compare() into a printable terminal table. Automatically selects the most readable time unit (ns, µs, ms, s).


Tutorial Notebook

A step-by-step tutorial with all four functions is available as a Jupyter notebook. Click below to open it directly in Google Colab — no local setup required:

Open In Colab


Running with Docker

# Build the image
docker build -t bencheetah .

# Run the demo (prints tables + saves scaling_sort.png inside the container)
docker run --rm bencheetah

# Copy the chart out of the container
docker run --rm -v "$PWD":/out bencheetah \
  sh -c "python examples/demo.py && cp scaling_sort.png /out/"

# Run the test suite
docker run --rm bencheetah pytest tests/ -v

Development

git clone https://github.com/JobAlcantara/bencheetah.git
cd bencheetah
pip install -e ".[dev]"
pytest tests/ -v

Project Structure

bencheetah/
├── src/
│   └── bencheetah/
│       ├── __init__.py
│       ├── core.py          # benchmark() and compare()
│       ├── formatters.py    # format_results()
│       └── plotter.py       # scale_benchmark() and plot_scaling()
├── tests/
│   └── test_bencheetah.py
├── examples/
│   └── demo.py
├── notebooks/
│   └── tutorial.ipynb
├── .github/
│   └── workflows/
│       └── ci.yml
├── Dockerfile
└── pyproject.toml

License

MIT © JobAlcantara

Project details


Download files

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

Source Distribution

bencheetah-0.2.0.tar.gz (14.0 kB view details)

Uploaded Source

Built Distribution

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

bencheetah-0.2.0-py3-none-any.whl (10.5 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for bencheetah-0.2.0.tar.gz
Algorithm Hash digest
SHA256 cd93938b1edba7c16f374db63f241cc8936214b7fa5aff2e4a4b8de758e18a38
MD5 8e2fd3816753237a0df00c262e9bc14f
BLAKE2b-256 8584c7e1af19606889e9aab0b8cfb933cc546db7d67feb76774c6f33390ac7ca

See more details on using hashes here.

Provenance

The following attestation bundles were made for bencheetah-0.2.0.tar.gz:

Publisher: ci.yml on JobAlcantara/bencheetah

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

File details

Details for the file bencheetah-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: bencheetah-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 10.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for bencheetah-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0f5bea0a06bfc6f83f09020ab6bc04164527a29fb9145ba3af7e3c719708da65
MD5 5516352c800c75068ff36e7096e76ad4
BLAKE2b-256 0c6fcb0cea3ba38664d30258f7f6ecfccdfaa4a05b10b1dfc5d7f025e1f622e1

See more details on using hashes here.

Provenance

The following attestation bundles were made for bencheetah-0.2.0-py3-none-any.whl:

Publisher: ci.yml on JobAlcantara/bencheetah

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

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page