Source code for pwtools.timer

from time import time

[docs] class TagTimer: """ Helper class for timimg. It's meant to be used for manually inspecting code. Examples -------- .. code-block:: python tt = TagTimer() # print some message tt.p('start profiling part 1') # set start time for tag 'outer-loop' tt.t('outer-loop') for i ... <code> # set start time for tag 'inner-loop' tt.t('inner-loop') for j ... <code> # use case 1: get stop time and print timing (stop - start) for tag # 'inner-loop' immediately tt.pt('inner-loop') # use case 2: get stop time and store it tt.t('outer-loop') <some_more_code> # print timing (stop - start) for tag 'outer-loop' later (maybe in some # summary statistic or so) tt.pt('outer-loop') # it's possible to re-use tags tt.p('start profiling part 2') tt.t('outer-loop') for i ... <code> tt.t('inner-loop') .... """
[docs] def __init__(self, silence=False): self.none_ar = [None, None] # {'tag0': array([val0, val1]), 'tag1': array([val2, val3]), ...} # Every `val` can be None or a float (= a time value). `tag` is a tag # string like 'outer-loop'. self.time_ar_dict = dict() self.silence = silence
[docs] def t(self, tag): """ Assign and save a numeric value (a time value) in a storage array associated with `tag`. Parameters ---------- tag : anything hashable a tag (most likely a string) associated with a storage array Notes ----- After initialization, self.time_ar_dict[tag] == [None, None]. | The 1st call assings self.time_ar_dict[tag][0] = <time>. | The 2nd call assings self.time_ar_dict[tag][1] = <time>. | The 3rd call resets self.time_ar_dict[tag] = [None, None] | and recursively calls t(), which then does the the same as the 1st. | ... """ # Init a new array for a new tag. if tag not in self.time_ar_dict: # numpy arrays: # Use array method copy(), otherwise, we would use the exact same # array everytime, since 'a = numpy.array(...); b = a' only creates # a *view* of `a` (like a pointer). # lists: # Behave like numpy arrays (b = a is view of a). Must also copy: # b = a[:] (use slicing). self.time_ar_dict[tag] = self.none_ar[:] # array is [None, None], assign the 1st time value. if self.time_ar_dict[tag][0] is None: self.time_ar_dict[tag][0] = time() # The second time value. elif self.time_ar_dict[tag][1] is None: self.time_ar_dict[tag][1] = time() # array is [<val>, <val>], so reset to [None, None] and # assign the 1st time value. else: self.time_ar_dict[tag] = self.none_ar[:] self.t(tag)
[docs] def pt(self, tag, msg=''): """ Print time difference since last ``t(tag)`` call for `tag`, which is ``self.time_ar_dict[tag][1] - self.time_ar_dict[tag][0]``. Parameters ---------- tag : anything hashable a tag (most likely a string) associated with a storage array msg : string Extra string to be printed along with the time difference. """ if tag not in self.time_ar_dict: raise ValueError("array for tag '%s' not jet initialized; " %tag\ + "you have to call t() first.") # hmm ... array is [None, None] .. shouldn't be # list test: [a, a] == [a, a] -> True if self.none_ar == self.time_ar_dict[tag]: raise ValueError("time array for tag '%s' or none_ar is wrong:\n" "time array: %s\n" "none_ar: %s\n" %(tag, str(self.time_ar_dict[tag]), str(self.none_ar))) # array is [<val>, None] (use case 1) or [<val>, <val>] (use case 2) if self.time_ar_dict[tag][0] is not None: # [<val>, None], assign second time if self.time_ar_dict[tag][1] is None: self.t(tag) self.p("%s: %s time: %s" %(tag, msg,\ self.time_ar_dict[tag][1] - self.time_ar_dict[tag][0])) else: raise ValueError("illegal array content for tag '%s' " %tag)
[docs] def p(self, msg): """ Simply print `msg`. """ if not self.silence: print("--TagTimer--: {}".format(msg))