os_helper.profile_utils module

Profiling Utilities

Context managers for timing code blocks at three different levels:

  • wall_timer — real elapsed wall-clock time (time.perf_counter).

  • cpu_timer — CPU time consumed by the current process across all

    threads (time.process_time). Excludes I/O / sleep and subprocesses.

  • gpu_timer — GPU execution time via PyTorch CUDA events (or

    torch.mps.synchronize + wall-clock on Apple Silicon, since MPS does not expose timing events).

The three context managers yield a small dict {"seconds": float, "milliseconds": float} populated when the with block exits, so the result survives beyond the context.

Plus a pair of MATLAB-flavored convenience functions for the “sprinkle-a-timer-mid-script” style:

  • tic / toc — wall-clock stopwatch. tic() resets the implicit

    global timer and returns a handle; toc() reads elapsed seconds since the last tic() (or since the passed-in handle, for nested timings).

Author:
os_helper.profile_utils.cpu_timer()[source]

Measure CPU time consumed by the current process using time.process_time() (sums user + system CPU across all threads).

Differs from wall_timer() in two important ways:

  • It excludes time spent blocked on I/O, sleeping, or waiting on the GPU — so it isolates “actual computation done by Python+native code”.

  • It excludes subprocesses (ffmpeg, etc.). For those, use wall_timer() or os.times() directly.

On a multi-threaded computation it can report more seconds than wall-clock — that’s intentional: it counts the CPU work, not the elapsed time.

Yields:

dict{"seconds": float, "milliseconds": float}.

Return type:

Generator[dict[str, float], None, None]

Examples

>>> with cpu_timer() as t:
...     total = sum(i * i for i in range(1_000_000))
>>> assert t["seconds"] > 0
os_helper.profile_utils.gpu_timer(backend='auto')[source]

Measure GPU execution time, synchronizing before and after the block.

Backends

  • "cuda" — uses torch.cuda.Event(enable_timing=True) pairs, which give microsecond-level GPU-side timing.

  • "mps" — Apple Silicon. PyTorch’s MPS backend does not expose timing events, so this falls back to torch.mps.synchronize() + time.perf_counter() around the block. Accuracy ~1 ms.

  • "auto" — pick CUDA if available, else MPS, else raise.

Both paths synchronize before and after the block so the measured duration corresponds to actual GPU work, not just kernel-queue submission. Without synchronization, GPU ops are asynchronous and the timer would understate the cost dramatically.

param backend:

"auto" (default), "cuda", or "mps".

type backend:

str, optional

Yields:

dict{"seconds": float, "milliseconds": float}.

raises RuntimeError:

If PyTorch is not installed, or if the requested backend is unavailable on this machine.

raises ValueError:

If backend is not one of "auto", "cuda", "mps".

Examples

>>> import torch
>>> if torch.cuda.is_available():
...     x = torch.randn(2048, 2048, device="cuda")
...     with gpu_timer() as t:
...         y = x @ x
...     print(t["milliseconds"])
Parameters:

backend (str)

Return type:

Generator[dict[str, float], None, None]

os_helper.profile_utils.tic()[source]

Start (or restart) the implicit global stopwatch.

Returns the start timestamp so callers can pin a handle for nested or interleaved measurements:

>>> t_outer = tic()
>>> # ... work ...
>>> t_inner = tic()      # implicit global now points at t_inner
>>> # ... more work ...
>>> toc(t_inner)         # explicit handle works regardless of which tic() was last
>>> toc(t_outer)
Returns:

time.perf_counter() snapshot, usable as a handle for toc().

Return type:

float

os_helper.profile_utils.toc(handle=None, *, log=False)[source]

Return seconds elapsed since the matching tic() call.

Parameters:
  • handle (float, optional) – Handle returned by tic(). If None, the implicit “last tic” timestamp is used.

  • log (bool, optional) – If True, log the elapsed time at INFO level via the root logger.

Returns:

Seconds elapsed (does not reset the timer — call tic() again to restart).

Return type:

float

Raises:

RuntimeError – If called with no handle and no prior tic().

Examples

>>> tic()
>>> # ... work ...
>>> elapsed = toc()
os_helper.profile_utils.wall_timer()[source]

Measure real elapsed wall-clock time using time.perf_counter().

Use this when you want to know “how long did this take to run from the user’s perspective” — it includes I/O, sleeps, GPU waits, and subprocess time.

Yields:

dict{"seconds": float, "milliseconds": float}, both fields populated when the with block exits.

Return type:

Generator[dict[str, float], None, None]

Examples

>>> with wall_timer() as t:
...     time.sleep(0.05)
>>> assert t["seconds"] >= 0.05