Skip to content

Commit cddc48c

Browse files
author
David Erb
committed
adds profiler
1 parent c2fe586 commit cddc48c

File tree

1 file changed

+45
-13
lines changed

1 file changed

+45
-13
lines changed

src/dls_utilpack/profiler.py

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,42 @@
66
logger = logging.getLogger(__name__)
77

88

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

17-
def __init__(self, label):
17+
def __init__(self, label: str, profiler: Profiler):
18+
self.__profiler = profiler
19+
1820
self.__label = label
1921
self.__start_time = 0
20-
self.__seconds = 0.0
21-
self.__count = 0
2222

2323
def __enter__(self):
2424
self.__start_time = time.time()
2525

2626
def __exit__(self, exc_type, exc_val, exc_tb):
27-
self.__seconds = time.time() - self.__start_time
28-
self.__count += 1
27+
self.__profiler.accumulate(
28+
self.__label,
29+
time.time() - self.__start_time,
30+
)
31+
32+
33+
class Profile:
34+
"""
35+
Class that holds the total execution time and call count of potentially multiple executions of the same label.
36+
Reports its contents as a single-line string.
37+
38+
TODO: Make profiles nestable by accumulating them at the context close.
39+
"""
40+
41+
def __init__(self, label):
42+
self.__label = label
43+
self.__seconds = 0.0
44+
self.__count = 0
2945

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

4864
def __init__(self):
4965
self.__profiles = {}
66+
self.__lock = threading.RLock()
5067

51-
def profile(self, label: str) -> Profile:
68+
def profile(self, label: str) -> Context:
5269
"""
53-
Return the profile for the given label. Uses previously existing profile, if any, or makes a new instance.
70+
Return a context to hold the profile timing.
5471
5572
Args:
5673
label (str): label identifying the profile
5774
5875
Returns:
5976
Profile: a new profile object, or previously existing one
6077
"""
61-
profile = self.__profiles.get(label)
62-
if profile is None:
63-
profile = Profile(label)
64-
self.__profiles[label] = profile
78+
return Context(label, self)
79+
80+
def accumulate(self, label: str, seconds: float) -> None:
81+
"""
82+
Accumulate a report into the profile for the given label.
83+
Uses previously existing profile, if any, or makes a new instance.
84+
85+
Args:
86+
label (str): label identifying the profile
6587
66-
return profile
88+
Returns:
89+
Profile: a new profile object, or previously existing one
90+
"""
91+
with self.__lock:
92+
profile = self.__profiles.get(label)
93+
if profile is None:
94+
profile = Profile(label)
95+
self.__profiles[label] = profile
96+
97+
profile.seconds += seconds
98+
profile.count += 1
6799

68100
def __str__(self) -> str:
69101
lines = []

0 commit comments

Comments
 (0)