Skip to content

Commit

Permalink
adds profiler
Browse files Browse the repository at this point in the history
  • Loading branch information
David Erb committed May 18, 2023
1 parent c2fe586 commit cddc48c
Showing 1 changed file with 45 additions and 13 deletions.
58 changes: 45 additions & 13 deletions src/dls_utilpack/profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,42 @@
logger = logging.getLogger(__name__)


class Profile:
class Context:
"""
Class that holds the total execution time and call count of potentially multiple executions of the same label.
Reports its contents as a single-line string.
TODO: Make profiles nestable by accumulating them at the context close.
"""

def __init__(self, label):
def __init__(self, label: str, profiler: Profiler):
self.__profiler = profiler

self.__label = label
self.__start_time = 0
self.__seconds = 0.0
self.__count = 0

def __enter__(self):
self.__start_time = time.time()

def __exit__(self, exc_type, exc_val, exc_tb):
self.__seconds = time.time() - self.__start_time
self.__count += 1
self.__profiler.accumulate(
self.__label,
time.time() - self.__start_time,
)


class Profile:
"""
Class that holds the total execution time and call count of potentially multiple executions of the same label.
Reports its contents as a single-line string.
TODO: Make profiles nestable by accumulating them at the context close.
"""

def __init__(self, label):
self.__label = label
self.__seconds = 0.0
self.__count = 0

def __str__(self):
if self.__count == 0:
Expand All @@ -47,23 +63,39 @@ class Profiler:

def __init__(self):
self.__profiles = {}
self.__lock = threading.RLock()

def profile(self, label: str) -> Profile:
def profile(self, label: str) -> Context:
"""
Return the profile for the given label. Uses previously existing profile, if any, or makes a new instance.
Return a context to hold the profile timing.
Args:
label (str): label identifying the profile
Returns:
Profile: a new profile object, or previously existing one
"""
profile = self.__profiles.get(label)
if profile is None:
profile = Profile(label)
self.__profiles[label] = profile
return Context(label, self)

def accumulate(self, label: str, seconds: float) -> None:
"""
Accumulate a report into the profile for the given label.
Uses previously existing profile, if any, or makes a new instance.
Args:
label (str): label identifying the profile
return profile
Returns:
Profile: a new profile object, or previously existing one
"""
with self.__lock:
profile = self.__profiles.get(label)
if profile is None:
profile = Profile(label)
self.__profiles[label] = profile

profile.seconds += seconds
profile.count += 1

def __str__(self) -> str:
lines = []
Expand Down

0 comments on commit cddc48c

Please sign in to comment.