Source code for eotransform.utilities.profiling

import logging
import os
import time
from contextlib import contextmanager
from functools import wraps
from typing import Optional

PERFORMANCE_LOG_ENV_VAR = 'CORRELATION_MAP_PERFORMANCE_LOG'
NANOSECONDS_PER_SECOND = 1e9

[docs]class PerformanceClock: def __init__(self, name: Optional[str] = ""): self._measures = [] self._name = name @property def name(self) -> str: return self._name @contextmanager def measure(self): start = time.perf_counter_ns() yield self._measures.append((time.perf_counter_ns() - start) / NANOSECONDS_PER_SECOND) @property def total_measures(self): return sum(self._measures) @property def mean_measures(self): return self.total_measures / len(self._measures) def drop_first(self): self._measures = self._measures[1:] return self
_LOGGING_FREQUENCIES = dict()
[docs]def log(domain: str): class _FrequencySetter: def __init__(self, domain): self._domain = domain def every(self, frequency: int): _LOGGING_FREQUENCIES[self._domain] = frequency return _FrequencySetter(domain)
[docs]def clock_performance(domain: str): def _clock_performance(func): if not os.environ.get(PERFORMANCE_LOG_ENV_VAR, False): return func clock = PerformanceClock() log_n = 0 freq = None @wraps(func) def _decorator(*args, **kwargs): nonlocal freq nonlocal log_n nonlocal clock if freq is None: freq = _LOGGING_FREQUENCIES.get(domain, 0) if freq == 0: return func(*args, **kwargs) with clock.measure(): response = func(*args, **kwargs) log_n += 1 if log_n % freq == 0: logging.info(f"{domain}::{func.__name__}: {clock.mean_measures}") return response return _decorator return _clock_performance