Skip to content
Snippets Groups Projects
Commit 91c541fe authored by Jan David Mol's avatar Jan David Mol
Browse files

L2SS-1262: Maintain statistics per object in TimeIt

parent e6b0a8b4
Branches
Tags
1 merge request!548L2SS-1262: Maintain statistics per object in TimeIt
...@@ -150,7 +150,7 @@ class BeamDevice(LOFARDevice): ...@@ -150,7 +150,7 @@ class BeamDevice(LOFARDevice):
doc="Time it took to compute weights", doc="Time it took to compute weights",
unit="s", unit="s",
dtype=numpy.float64, dtype=numpy.float64,
fget=lambda self: self._compute_weights.statistics["last"] or 0, fget=lambda self: self._compute_weights.get_statistic(self)["last"] or 0,
) )
Duration_preparation_period_slack_R = attribute( Duration_preparation_period_slack_R = attribute(
...@@ -158,7 +158,7 @@ class BeamDevice(LOFARDevice): ...@@ -158,7 +158,7 @@ class BeamDevice(LOFARDevice):
doc="Slack between computing and applying weights", doc="Slack between computing and applying weights",
unit="s", unit="s",
dtype=numpy.float64, dtype=numpy.float64,
fget=lambda self: self._wait_to_apply_weights.statistics["last"] or 0, fget=lambda self: self._wait_to_apply_weights.get_statistic(self)["last"] or 0,
) )
Duration_apply_weights_R = attribute( Duration_apply_weights_R = attribute(
...@@ -166,7 +166,7 @@ class BeamDevice(LOFARDevice): ...@@ -166,7 +166,7 @@ class BeamDevice(LOFARDevice):
doc="Time it took to upload weights", doc="Time it took to upload weights",
unit="s", unit="s",
dtype=numpy.float64, dtype=numpy.float64,
fget=lambda self: self._apply_weights.statistics["last"] or 0, fget=lambda self: self._apply_weights.get_statistic(self)["last"] or 0,
) )
Nr_update_pointing_exceptions_R = attribute( Nr_update_pointing_exceptions_R = attribute(
...@@ -275,7 +275,7 @@ class BeamDevice(LOFARDevice): ...@@ -275,7 +275,7 @@ class BeamDevice(LOFARDevice):
def _wait_to_apply_weights(self, timestamp: datetime.datetime): def _wait_to_apply_weights(self, timestamp: datetime.datetime):
# expected time required to upload weights to hardware (use last 10 measured durations) # expected time required to upload weights to hardware (use last 10 measured durations)
expected_application_time = median( expected_application_time = median(
self._apply_weights.statistics["history"][-10:] or [0.1] self._apply_weights.get_statistic(self)["history"][-10:] or [0.1]
) )
# wait until provided time occurs, but don't start sleeping long here # wait until provided time occurs, but don't start sleeping long here
......
...@@ -78,15 +78,15 @@ def fault_on_error(): ...@@ -78,15 +78,15 @@ def fault_on_error():
return inner return inner
def TimeIt(log_function=None): def TimeIt(log_function=None, max_history_len=10):
""" """
Wrapper to time calls. Stores the timing log in a Wrapper to time calls, per object. Stores the timing log in a
<function>.statistics property as a dict with the following <function>.statistics property as a dict with the following
information: information:
"count": number of times the function was called "count": number of times the function was called
"last": duration of the last invocation "last": duration of the last invocation
"history": last 10 durations "history": last "max_history_len" durations
NOTE: If the function called throws an exception, timing information NOTE: If the function called throws an exception, timing information
is not logged or recorded. Those calls are expected to be is not logged or recorded. Those calls are expected to be
...@@ -94,12 +94,14 @@ def TimeIt(log_function=None): ...@@ -94,12 +94,14 @@ def TimeIt(log_function=None):
""" """
def inner(func): def inner(func):
statistics = { default_statistic = {
"count": 0, "count": 0,
"last": None, "last": None,
"history": [], "history": [],
} }
statistics = {}
@wraps(func) @wraps(func)
def timer_wrapper(self, *args, **kwargs): def timer_wrapper(self, *args, **kwargs):
# time function call # time function call
...@@ -107,10 +109,16 @@ def TimeIt(log_function=None): ...@@ -107,10 +109,16 @@ def TimeIt(log_function=None):
result = func(self, *args, **kwargs) result = func(self, *args, **kwargs)
after = time.monotonic_ns() after = time.monotonic_ns()
# maintain statistics per object (self)
if self not in statistics:
statistics[self] = default_statistic.copy()
# store measurement # store measurement
statistics["count"] += 1 statistics[self]["count"] += 1
statistics["last"] = (after - before) / 1e9 statistics[self]["last"] = (after - before) / 1e9
statistics["history"] = statistics["history"][-9:] + [statistics["last"]] statistics[self]["history"] = statistics[self]["history"][
-(max_history_len - 1) :
] + [statistics[self]["last"]]
if log_function: if log_function:
log_function( log_function(
...@@ -120,8 +128,14 @@ def TimeIt(log_function=None): ...@@ -120,8 +128,14 @@ def TimeIt(log_function=None):
# return function result (if any) # return function result (if any)
return result return result
# provide a way to access all collected statistics
timer_wrapper.statistics = statistics timer_wrapper.statistics = statistics
# get the statistics for a specific object
timer_wrapper.get_statistic = lambda self: statistics.get(
self, default_statistic.copy()
)
return timer_wrapper return timer_wrapper
return inner return inner
...@@ -81,7 +81,7 @@ class DigitalBeam(BeamDevice): ...@@ -81,7 +81,7 @@ class DigitalBeam(BeamDevice):
Duration_delays_R = attribute( Duration_delays_R = attribute(
access=AttrWriteType.READ, access=AttrWriteType.READ,
dtype=numpy.float64, dtype=numpy.float64,
fget=lambda self: self._delays.statistics["last"] or 0, fget=lambda self: self._delays.get_statistic(self)["last"] or 0,
) )
input_select_RW = attribute( input_select_RW = attribute(
......
...@@ -465,7 +465,8 @@ class SDP(OPCUADevice): ...@@ -465,7 +465,8 @@ class SDP(OPCUADevice):
unit="s", unit="s",
access=AttrWriteType.READ, access=AttrWriteType.READ,
dtype=numpy.float64, dtype=numpy.float64,
fget=lambda self: self.read_subband_frequency_R.statistics["last"] or 0, fget=lambda self: self.read_subband_frequency_R.get_statistic(self)["last"]
or 0,
) )
def read_antenna_type_RW(self): def read_antenna_type_RW(self):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment