Skip to main content

Scripts for benchmarking

Project description

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.

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

porter_bench-0.2.2.tar.gz (38.0 kB view details)

Uploaded Source

Built Distribution

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

porter_bench-0.2.2-py3-none-any.whl (39.5 kB view details)

Uploaded Python 3

File details

Details for the file porter_bench-0.2.2.tar.gz.

File metadata

  • Download URL: porter_bench-0.2.2.tar.gz
  • Upload date:
  • Size: 38.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for porter_bench-0.2.2.tar.gz
Algorithm Hash digest
SHA256 29f53a3c7cd4bd0cac02d55e12c7609298b271b4a6dd134dea2f36dbb17b2f4b
MD5 ec09f12bfa12ff56a9bd57d9b7f02dd0
BLAKE2b-256 dc47f670a8ee4d29a96e0a8a5a2008e804a3b8ed7a9af0c7512e8ec2e85ded40

See more details on using hashes here.

File details

Details for the file porter_bench-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: porter_bench-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 39.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for porter_bench-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 faccf17dbde45a1bc3cc4f954e7cf5cafc915b0c13ecda43768460bb70d4c410
MD5 34426137612f11c3ce1efc72683e3b34
BLAKE2b-256 0515980a8767aa8e59765f098c81c777a32940dd5741ead434ed93897fe22f17

See more details on using hashes here.

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