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 TICTOC_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 TICTOC_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 run the standalone script after make example:

python generate_plots.py --path . --output PLOTS --show

Plots are saved to PLOTS/ as <name>_times.png, <name>_bars.png, <name>_crono.png, <name>_memory.png.

Output files

All JSON files are written under TICTOC_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

TICTOC_TOGGLES

TICTOC_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).

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

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

from porter_bench import TICTOC_TOGGLES

if TICTOC_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.0.tar.gz (36.4 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.0-py3-none-any.whl (36.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: porter_bench-0.2.0.tar.gz
  • Upload date:
  • Size: 36.4 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.0.tar.gz
Algorithm Hash digest
SHA256 79063c2ee888bf984efd50403da3e867fe2cab1e802c64ae1250a4fc2b1d0f50
MD5 14106963e113b24112105e9d2be4398a
BLAKE2b-256 6c9212cd513fb090b1f3457e260ad4da5e26e5927eb47fbaf5e078a70f5cc19a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: porter_bench-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 36.6 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8338f3a87d9559837e1a530fd6120265483e240b63b7feeccfae084f2302fee5
MD5 40bbd40af5147c0fecbc6f33e6562f2e
BLAKE2b-256 c95ac1be453b5c802b59baa3d4a03f7f3596c82846f98e312be82067a2657b7f

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