-
-
Save datavudeja/3a6125dbc692276e9a6ca7bf8fb74197 to your computer and use it in GitHub Desktop.
Cookbook Recipes for timing blocks of code at runtime.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| webapp/core/utilities/stopwatch.py | |
| Example Usage: | |
| ``` | |
| def countdown(n): | |
| while n > 0: | |
| n -= 1 | |
| # Use 1: Explicit start/stop | |
| t = StopwatchTimer() | |
| t.start() | |
| countdown(1000000) | |
| t.stop() | |
| print(t.elapsed) | |
| # Use 2: As a context manager | |
| with t: | |
| countdown(1000000) | |
| print(t.elapsed) | |
| with StopwatchTimer() as t2: | |
| countdown(1000000) | |
| print(t2.elapsed) | |
| ``` | |
| """ | |
| import time | |
| from contextlib import contextmanager | |
| from typing import Any, Callable, Optional | |
| from functools import wraps | |
| class StopwatchTimer: | |
| """StopwatchTimer | |
| This class defines a timer that can be started, stopped, and reset | |
| as needed by the user. Keep track of the total elapsed time in | |
| the elapsed attribute. | |
| Info: the `time.perf_counter()` function always uses the | |
| highest-resolution timer available on the system. | |
| """ | |
| def __init__(self, func: Callable[[], float] = time.perf_counter): | |
| """__init__ | |
| Args: | |
| func (Callable[[], float]): | |
| default=time.perf_counter | |
| """ | |
| self.elapsed: float = 0.0 | |
| self._func: Callable[[], float] = func | |
| self._start: Optional[float] = None | |
| def start(self): | |
| """start""" | |
| if self._start is not None: | |
| raise RuntimeError("Already started") | |
| self._start = self._func() | |
| def stop(self): | |
| """stop""" | |
| if self._start is None: | |
| raise RuntimeError("Not started") | |
| end = self._func() | |
| self.elapsed += end - self._start | |
| self._start = None | |
| def reset(self): | |
| """reset""" | |
| self.elapsed = 0.0 | |
| @property | |
| def running(self): | |
| """running""" | |
| return self._start is not None | |
| def __enter__(self): | |
| """__enter__""" | |
| self.start() | |
| return self | |
| def __exit__(self, *args): | |
| """__exit__""" | |
| self.stop() | |
| @staticmethod | |
| def time_function(method=time.process_time): | |
| """Time function decorator | |
| - Select between either: | |
| - `perf_counter`: wall-clock time | |
| - or | |
| - `process_time`: process time | |
| Simple method decorator for the selected profiling of functions, | |
| a short decorator can be useful. | |
| Example Usage: | |
| ``` | |
| if __name__ == "__main__": | |
| @StopwatchTimer.time_function() | |
| def countdown(n): | |
| while n > 0: | |
| n -= 1 | |
| countdown(10000000) | |
| ``` | |
| """ | |
| def decorate(func: Callable[[Any, ...], Any]) -> Any: | |
| """decorate | |
| Args: | |
| func (Callable[[Any, ...], Any]): | |
| Returns: | |
| (Any) | |
| """ | |
| # noinspection PyUnresolvedReferences | |
| @wraps(func) | |
| def wrapper(*args: Any, **kwargs: Any) -> Any: | |
| """wrapper | |
| Args: | |
| *args (Any): | |
| **kwargs (Any): | |
| Returns: | |
| (Any) | |
| """ | |
| start = method() | |
| ret = func(*args, **kwargs) | |
| end = method() | |
| print(f"{func.__module__}.{func.__name__} : {end - start}") | |
| return ret | |
| return wrapper | |
| return decorate | |
| @staticmethod | |
| @contextmanager | |
| def time_block(label: str, method: Callable[[], float] = time.perf_counter) -> None: | |
| """Time Block | |
| Time the encapsulated block of code within the context manager. | |
| Args: | |
| label (str): | |
| method (Callable[[], float]): | |
| default=time.perf_counter | |
| Returns: | |
| (None) | |
| Example Usage: | |
| ``` | |
| if __name__ == "__main__": | |
| with StopwatchTimer.time_block("counting"): | |
| n = 10000000 | |
| while n > 0: | |
| n -= 1 | |
| ``` | |
| """ | |
| start = method() | |
| try: | |
| yield | |
| finally: | |
| end = method() | |
| print(f"{label} : {end - start}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment