Source code for q2m3.profiling.timing

# Copyright (c) 2026 Ye Jun <yjmaxpayne@hotmail.com>
# SPDX-License-Identifier: MIT

"""
General-purpose timing utilities for q2m3.

Provides lightweight profiling tools for measuring code section and function
execution times. These utilities are independent of QPE-specific profiling
and can be used anywhere in the codebase.
"""

import functools
import time
from collections.abc import Callable
from contextlib import contextmanager
from typing import Any


[docs] @contextmanager def profile_section(name: str, verbose: bool = True): """Context manager for profiling a code section. Args: name: Name of the section being profiled verbose: Whether to print timing information Yields: dict: A timing info dictionary that gets updated with elapsed time Example:: with profile_section("QPE calculation") as timing: result = run_qpe() print(f"Elapsed: {timing['elapsed']:.3f}s") """ timing_info = {"start": 0.0, "end": 0.0, "elapsed": 0.0, "name": name} timing_info["start"] = time.perf_counter() try: yield timing_info finally: timing_info["end"] = time.perf_counter() timing_info["elapsed"] = timing_info["end"] - timing_info["start"] if verbose: print(f"[Profile] {name}: {timing_info['elapsed']:.3f}s")
[docs] def profile_function(func: Callable = None, *, verbose: bool = True) -> Callable: """Decorator for profiling a function's execution time. Args: func: The function to profile verbose: Whether to print timing information Returns: Wrapped function that tracks execution time Example:: @profile_function def compute_energy(): ... @profile_function(verbose=False) def silent_compute(): ... """ def decorator(fn: Callable) -> Callable: @functools.wraps(fn) def wrapper(*args, **kwargs) -> Any: start = time.perf_counter() try: result = fn(*args, **kwargs) return result finally: elapsed = time.perf_counter() - start if verbose: print(f"[Profile] {fn.__name__}: {elapsed:.3f}s") # Store timing info on the wrapper for inspection wrapper._last_elapsed = 0.0 return wrapper # Handle both @profile_function and @profile_function() syntax if func is not None: return decorator(func) return decorator
[docs] class ProfilingStats: """Accumulator for profiling statistics across multiple runs.""" def __init__(self, name: str = "default"): self.name = name self.timings: list[float] = []
[docs] def record(self, elapsed: float) -> None: """Record a timing measurement.""" self.timings.append(elapsed)
@property def total(self) -> float: """Total elapsed time.""" return sum(self.timings) @property def count(self) -> int: """Number of recorded timings.""" return len(self.timings) @property def mean(self) -> float: """Mean elapsed time.""" if not self.timings: return 0.0 return self.total / self.count @property def min(self) -> float: """Minimum elapsed time.""" if not self.timings: return 0.0 return min(self.timings) @property def max(self) -> float: """Maximum elapsed time.""" if not self.timings: return 0.0 return max(self.timings)
[docs] def summary(self) -> str: """Return a summary string of profiling stats.""" if not self.timings: return f"{self.name}: No timings recorded" return ( f"{self.name}: " f"count={self.count}, total={self.total:.3f}s, " f"mean={self.mean:.3f}s, min={self.min:.3f}s, max={self.max:.3f}s" )
def __repr__(self) -> str: return self.summary()