| | """ |
| | Timing utilities for performance measurement. |
| | """ |
| |
|
| | import time |
| | from contextlib import contextmanager |
| | from typing import Dict, Generator, Optional |
| |
|
| | from app.core.logging import get_logger |
| |
|
| | logger = get_logger(__name__) |
| |
|
| |
|
| | class Timer: |
| | """ |
| | Timer class for measuring execution time of code blocks. |
| | |
| | Usage: |
| | timer = Timer() |
| | with timer.measure("inference"): |
| | # do inference |
| | with timer.measure("fusion"): |
| | # do fusion |
| | timings = timer.get_timings() |
| | """ |
| | |
| | def __init__(self): |
| | self._start_time: Optional[float] = None |
| | self._timings: Dict[str, int] = {} |
| | self._total_start: Optional[float] = None |
| | |
| | def start_total(self) -> None: |
| | """Start the total timer.""" |
| | self._total_start = time.perf_counter() |
| | |
| | def stop_total(self) -> None: |
| | """Stop the total timer and record the duration.""" |
| | if self._total_start is not None: |
| | elapsed_ms = int((time.perf_counter() - self._total_start) * 1000) |
| | self._timings["total"] = elapsed_ms |
| | |
| | @contextmanager |
| | def measure(self, name: str) -> Generator[None, None, None]: |
| | """ |
| | Context manager to measure execution time of a block. |
| | |
| | Args: |
| | name: Name for this timing measurement |
| | |
| | Yields: |
| | None |
| | """ |
| | start = time.perf_counter() |
| | try: |
| | yield |
| | finally: |
| | elapsed_ms = int((time.perf_counter() - start) * 1000) |
| | self._timings[name] = elapsed_ms |
| | logger.debug(f"Timer [{name}]: {elapsed_ms}ms") |
| | |
| | def record(self, name: str, duration_ms: int) -> None: |
| | """ |
| | Manually record a timing. |
| | |
| | Args: |
| | name: Name for this timing |
| | duration_ms: Duration in milliseconds |
| | """ |
| | self._timings[name] = duration_ms |
| | |
| | def get_timings(self) -> Dict[str, int]: |
| | """ |
| | Get all recorded timings. |
| | |
| | Returns: |
| | Dictionary of timing name -> milliseconds |
| | """ |
| | return self._timings.copy() |
| | |
| | def get(self, name: str) -> Optional[int]: |
| | """ |
| | Get a specific timing. |
| | |
| | Args: |
| | name: Timing name |
| | |
| | Returns: |
| | Duration in milliseconds, or None if not recorded |
| | """ |
| | return self._timings.get(name) |
| | |
| | def reset(self) -> None: |
| | """Reset all timings.""" |
| | self._timings.clear() |
| | self._total_start = None |
| |
|
| |
|
| | def measure_time(func): |
| | """ |
| | Decorator to measure function execution time. |
| | |
| | Logs the execution time at DEBUG level. |
| | """ |
| | def wrapper(*args, **kwargs): |
| | start = time.perf_counter() |
| | try: |
| | result = func(*args, **kwargs) |
| | return result |
| | finally: |
| | elapsed_ms = int((time.perf_counter() - start) * 1000) |
| | logger.debug(f"Function [{func.__name__}]: {elapsed_ms}ms") |
| | return wrapper |
| |
|