Skip to main content

porter_bench

A Python benchmarking library for measuring execution time and memory usage across named pipeline steps and training loop iterations.

Installation

pip install -e ".[dev]"
pre-commit install
# or
make install

Quick start

from porter_bench import bench_dict

for i in range(10):
    bench_dict["my_pipeline"].gstep()   # boundary between iterations

    data = load()
    bench_dict["my_pipeline"].step("load")

    result = process(data)
    bench_dict["my_pipeline"].step("process")

    bench_dict["my_pipeline"].gstop()

bench_dict.save()  # writes JSON files to PORTER_BENCH_PERFORMANCE/<timestamp>/

Usage

Pipeline benchmarking

bench_dict["name"] lazily creates a Benchmarker. The gstep/gstop pair marks iteration boundaries; step(topic) records time for a named sub-step within that iteration.

from porter_bench import bench_dict

bench = bench_dict["pipeline"]
bench.set_save_on_gstop(4)  # auto-save every 4 iterations

for _ in range(20):
    bench.gstep()
    bench.step("load")
    bench.step("compute")
    bench.step("postprocess")
    bench.gstop()

bench_dict.save()

Training loop with IterBench

IterBench wraps any iterable and calls gstep()/gstop() automatically around each iteration:

from porter_bench import bench_dict
from porter_bench.GlobalBenchmarker import IterBench

for batch in IterBench(dataloader, bench_dict, "training"):
    bench_dict["training"].step("forward")
    bench_dict["training"].step("backward")

Memory tracking

bench = bench_dict["memory"]
bench.enable_memory_tracking(per_step=True)          # RAM tracking per step
bench.memory_benchmaker.enable_max_memory(poll_time=0.05)  # peak RAM polling

# Optional CUDA tracking (requires torch with CUDA)
bench.memory_benchmaker.enable_cuda_memory_tracking()

Low-level timer utilities

from porter_bench import timer
from porter_bench.basic import CountDownClock, TimedCounter

# Simple timer
timer.tic()
result = do_work()
elapsed = timer.toc()          # seconds since tic
elapsed = timer.ttoc()         # toc + reset

# Countdown
clock = CountDownClock(count_down_time=4.0)
while not clock.completed():
    print("time left:", clock.time_left())

# Frequency counter
counter = TimedCounter()
counter.start()
for _ in range(100):
    do_work()
    counter.count()
counter.stop()
print("frequency:", counter.get_frequency(), "Hz")

Auto-save options

bench.set_save_on_gstop(N)   # save every N iterations
bench.set_save_on_step(True)  # save after every step

Loading and visualising results

from porter_bench.utils import load_record
from porter_bench.DataHandler import DataHandler

record = load_record(".")          # loads latest run from PORTER_BENCH_PERFORMANCE/
handler = DataHandler({"run": record})

handler.plot_times(record_name="pipeline")
handler.make_bars(record_name="pipeline")
handler.plot_crono(record_name="pipeline")
handler.plot_memory_usage(record_name="memory")

Or use the porter-bench-plots CLI (installed with the package):

# Plot the latest run in the current directory
porter-bench-plots

# Specify search path and output directory
porter-bench-plots --path /path/to/project --output PLOTS

# Plot only specific benchmarker topics
porter-bench-plots --topics pipeline training

# Show plots interactively in addition to saving
porter-bench-plots --show

# Point directly at a specific record directory (skip auto-find)
porter-bench-plots --path PORTER_BENCH_PERFORMANCE/2024-01-01_12-00-00/run --no-latest

Or invoke as a module:

python -m porter_bench.plot_cli --path . --output PLOTS --show
Flag Default Description
--path PATH . Root dir containing PORTER_BENCH_PERFORMANCE/, or a specific record dir with --no-latest
--output DIR PLOTS Directory to save generated plots
--topics A B … all Restrict to specific benchmarker names
--show off Display plots interactively in addition to saving
--no-latest off Treat --path as a specific record directory instead of auto-finding the latest run

Plots are saved to PLOTS/ as <name>_times.png, <name>_bars.png, <name>_crono.png, <name>_memory.png, and <name>_cuda_memory.png (if CUDA data is present).

Output files

All JSON files are written under PORTER_BENCH_PERFORMANCE/<timestamp>/<name>/:

File Contents
*_STEP_DICT_DATA.json Per-iteration step timings
*_STEP_DICT_SUMMARY.json Aggregated mean/min/max stats
*_MEMORY.json RAM and CUDA memory snapshots

Development

make test    # pytest
make lint    # pre-commit run --all-files
make example # run example.py then generate_plots.py

PORTER_BENCH_TOGGLES

PORTER_BENCH_TOGGLES is an 8-bit binary string environment variable that exposes boolean feature flags for automating test variations without code changes. Each bit position is an independent toggle (index 0 = rightmost bit).

PORTER_BENCH_TOGGLES="00000001" pytest   # toggle 0 on
PORTER_BENCH_TOGGLES="00000011" pytest   # toggles 0 and 1 on
PORTER_BENCH_TOGGLES="10000000" pytest   # toggle 7 on

Inside the library, PORTER_BENCH_TOGGLES is parsed into a list[bool] of length 8, importable as:

from porter_bench import PORTER_BENCH_TOGGLES

if PORTER_BENCH_TOGGLES[0]:
    # behaviour variant A
else:
    # behaviour variant B

This lets you drive conditional code paths — alternative algorithms, stricter assertions, extra logging — purely from the environment, making it easy to test both branches in CI or a single pytest run.

Release files for porter-bench 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for porter-bench 0.2.2
File Size Uploaded
porter_bench-0.2.2.tar.gz 38.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for porter-bench 0.2.2
File Interpreter ABI Platform
porter_bench-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 77.5 kB

Release files / porter_bench-0.2.2.tar.gz

Download URL porter_bench-0.2.2.tar.gz
Size 38.0 kB
Tags Source
SHA-256 checksum
How to use checksums
29f53a3c7cd4bd0cac02d55e12c7609298b271b4a6dd134dea2f36dbb17b2f4b
BLAKE2b-256 checksum
How to use checksums
dc47f670a8ee4d29a96e0a8a5a2008e804a3b8ed7a9af0c7512e8ec2e85ded40
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.12

Release files / porter_bench-0.2.2-py3-none-any.whl

Download URL porter_bench-0.2.2-py3-none-any.whl
Size 39.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
faccf17dbde45a1bc3cc4f954e7cf5cafc915b0c13ecda43768460bb70d4c410
BLAKE2b-256 checksum
How to use checksums
0515980a8767aa8e59765f098c81c777a32940dd5741ead434ed93897fe22f17
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.12

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release 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