| 1 | #!/usr/bin/env python |
|---|
| 2 | # |
|---|
| 3 | # Author: Mike McKerns (mmckerns @caltech and @uqfoundation) |
|---|
| 4 | # Copyright (c) 2012-2016 California Institute of Technology. |
|---|
| 5 | # License: 3-clause BSD. The full license text is available at: |
|---|
| 6 | # - http://mmckerns.github.io/project/mystic/browser/mystic/LICENSE |
|---|
| 7 | |
|---|
| 8 | def timed(verbose=True): |
|---|
| 9 | def dec(f): |
|---|
| 10 | """decorator for timing a function""" |
|---|
| 11 | from time import time as now |
|---|
| 12 | __time = [True, None] |
|---|
| 13 | if not verbose: __time[0] = False |
|---|
| 14 | def time(stamp=False): |
|---|
| 15 | if not stamp: return __time[-1] |
|---|
| 16 | import datetime |
|---|
| 17 | return datetime.timedelta(seconds=__time[-1]) |
|---|
| 18 | def __verbose(on=True): |
|---|
| 19 | __time[0] = bool(on) |
|---|
| 20 | def func(*args, **kwds): |
|---|
| 21 | t = now() |
|---|
| 22 | res = f(*args, **kwds) |
|---|
| 23 | __time[-1] = now() - t |
|---|
| 24 | if __time[0]: |
|---|
| 25 | print "Timed: %s" % __time[-1] |
|---|
| 26 | return res |
|---|
| 27 | func.time = time |
|---|
| 28 | func.verbose = __verbose |
|---|
| 29 | return func |
|---|
| 30 | return dec |
|---|
| 31 | |
|---|
| 32 | |
|---|
| 33 | class Timer(object): |
|---|
| 34 | """ |
|---|
| 35 | Instances of timer objects that can be passed as timers. |
|---|
| 36 | Typically, a timer is attached to a monitor and is called |
|---|
| 37 | when the monitor is called. |
|---|
| 38 | |
|---|
| 39 | example usage... |
|---|
| 40 | >>> timer = Timer() |
|---|
| 41 | >>> timer.stamp = False |
|---|
| 42 | >>> timer() |
|---|
| 43 | >>> timer._t |
|---|
| 44 | 51.91421914100647 |
|---|
| 45 | >>> timer() |
|---|
| 46 | >>> timer._t |
|---|
| 47 | 74.009551048278809 |
|---|
| 48 | >>> timer.t |
|---|
| 49 | [51.91421914100647, 74.009551048278809] |
|---|
| 50 | >>> timer.stamp = True |
|---|
| 51 | >>> print timer._t |
|---|
| 52 | 0:01:14.009551 |
|---|
| 53 | >>> print timer.t0 |
|---|
| 54 | 2012-10-15 13:00:53.758812 |
|---|
| 55 | """ |
|---|
| 56 | def __init__(self, **kwds): |
|---|
| 57 | self.__on = kwds.get('on', False) |
|---|
| 58 | self.__off = 0 |
|---|
| 59 | self.__t = [] |
|---|
| 60 | self.__t0 = [self.__now()] |
|---|
| 61 | self.__stamp = kwds.get('stamp', True) |
|---|
| 62 | self.__lazy = kwds.get('lazy', True) |
|---|
| 63 | def __call__(self): |
|---|
| 64 | if self.__on or self.__lazy: |
|---|
| 65 | self.__on = True |
|---|
| 66 | self.__t.extend(self.__deadtime()) |
|---|
| 67 | self.__t.append(self.__now()) |
|---|
| 68 | self.__off = 0 |
|---|
| 69 | else: |
|---|
| 70 | self.__off += 1 |
|---|
| 71 | def __get_lazy(self): |
|---|
| 72 | return self.__lazy |
|---|
| 73 | def __set_lazy(self, ind): |
|---|
| 74 | """if True, 'call' will turn timer on""" |
|---|
| 75 | self.__lazy = bool(ind) |
|---|
| 76 | def __get_stamp(self): |
|---|
| 77 | return self.__stamp |
|---|
| 78 | def __set_stamp(self, ind): |
|---|
| 79 | """if True, _t & t0 return datetime object""" |
|---|
| 80 | self.__stamp = bool(ind) |
|---|
| 81 | def __get_on(self): |
|---|
| 82 | return self.__on |
|---|
| 83 | def __set_on(self, ind): |
|---|
| 84 | """if False, record 'nan' instead of a time""" |
|---|
| 85 | self.__on = bool(ind) |
|---|
| 86 | def __toggle(self): |
|---|
| 87 | """toggle the timer on/off""" |
|---|
| 88 | self.__on = not self.__on |
|---|
| 89 | def __reset(self): |
|---|
| 90 | """reset t0 to now""" |
|---|
| 91 | self.__t0.append(self.__now()) |
|---|
| 92 | #XXX: should reset to original kwds settings? (on, lazy, ...) |
|---|
| 93 | def __get_t0(self): |
|---|
| 94 | t = self.__t0[-1] |
|---|
| 95 | if not self.__stamp: return t |
|---|
| 96 | import datetime |
|---|
| 97 | return datetime.datetime.fromtimestamp(t) |
|---|
| 98 | def __set_t0(self, t): #XXX: allow setting t0 ? |
|---|
| 99 | self.__t0.append(t) |
|---|
| 100 | def __first(self): |
|---|
| 101 | """get all t0 as a list""" |
|---|
| 102 | return self.__t0 |
|---|
| 103 | def __now(self): |
|---|
| 104 | from time import time as now |
|---|
| 105 | return now() |
|---|
| 106 | def __deadtime(self): |
|---|
| 107 | from numpy import NaN |
|---|
| 108 | return [NaN] * self.__off |
|---|
| 109 | def __get_t(self): |
|---|
| 110 | from numpy import array |
|---|
| 111 | return list(array(self.__t + self.__deadtime()) - self.__t0[-1]) |
|---|
| 112 | def __last(self): |
|---|
| 113 | """just get the last t, instead of all t""" |
|---|
| 114 | if not self.__t: return None # require a 'call' |
|---|
| 115 | t = self.__t[-1] - self.__t0[-1] |
|---|
| 116 | if t < 0.0: return None # require a 'call' after a 'reset' |
|---|
| 117 | if not self.__stamp: return t |
|---|
| 118 | import datetime |
|---|
| 119 | return datetime.timedelta(seconds=t) |
|---|
| 120 | on = property(__get_on, __set_on) |
|---|
| 121 | toggle = property(__toggle) |
|---|
| 122 | reset = property(__reset) |
|---|
| 123 | _t0 = property(__first) # [t0, ...] |
|---|
| 124 | t0 = property(__get_t0,__set_t0) # t0 |
|---|
| 125 | _t = property(__last) # t |
|---|
| 126 | t = property(__get_t) # [t, ...] |
|---|
| 127 | stamp = property(__get_stamp, __set_stamp) |
|---|
| 128 | lazy = property(__get_lazy, __set_lazy) |
|---|
| 129 | |
|---|
| 130 | |
|---|
| 131 | from mystic.monitors import Monitor |
|---|
| 132 | class TimedMonitor(Monitor): |
|---|
| 133 | """A timed version of the basic Monitor. |
|---|
| 134 | |
|---|
| 135 | Every time the monitor is called, the time is also logged. |
|---|
| 136 | Timer is configurable through 'monitor.timer'. |
|---|
| 137 | """ |
|---|
| 138 | def __init__(self, **kwds):#, all=True): |
|---|
| 139 | timed = kwds.pop('timed', False) |
|---|
| 140 | #called = kwds.pop('lazy', True) |
|---|
| 141 | #stamp = kwds.pop('stamp', True) |
|---|
| 142 | super(TimedMonitor,self).__init__(**kwds) |
|---|
| 143 | self.timer = Timer(on=timed)#,lazy=called,stamp=stamp) |
|---|
| 144 | return |
|---|
| 145 | |
|---|
| 146 | def __call__(self, x, y, id=None, **kwds):#, best=0): |
|---|
| 147 | self.timer() |
|---|
| 148 | super(TimedMonitor,self).__call__(x, y, id, **kwds) |
|---|
| 149 | return |
|---|
| 150 | |
|---|
| 151 | pass |
|---|
| 152 | |
|---|
| 153 | |
|---|
| 154 | if __name__ == '__main__': |
|---|
| 155 | monitor = TimedMonitor() |
|---|
| 156 | monitor.timer.lazy = False |
|---|
| 157 | monitor([1],1) |
|---|
| 158 | monitor.timer.on = True |
|---|
| 159 | monitor([2],2) |
|---|
| 160 | monitor([3],3) |
|---|
| 161 | monitor.timer.toggle |
|---|
| 162 | print "x: %s" % monitor.x |
|---|
| 163 | print "y: %s" % monitor.y |
|---|
| 164 | print "t: %s" % monitor.timer.t |
|---|
| 165 | print "t0: %s" % monitor.timer.t0 |
|---|
| 166 | monitor.timer.stamp = False |
|---|
| 167 | print "Ran: %s seconds" % monitor.timer._t |
|---|
| 168 | monitor.timer.stamp = True |
|---|
| 169 | monitor.timer.reset |
|---|
| 170 | monitor([4],4) |
|---|
| 171 | print "x: %s" % monitor.x |
|---|
| 172 | print "y: %s" % monitor.y |
|---|
| 173 | print "t: %s" % monitor.timer.t |
|---|
| 174 | print "t0: %s" % monitor.timer.t0 |
|---|
| 175 | monitor.timer.stamp = False |
|---|
| 176 | print "Ran: %s seconds" % monitor.timer._t |
|---|
| 177 | monitor.timer.stamp = True |
|---|
| 178 | monitor.timer.toggle |
|---|
| 179 | monitor([5],5) |
|---|
| 180 | print "x: %s" % monitor.x |
|---|
| 181 | print "y: %s" % monitor.y |
|---|
| 182 | print "t: %s" % monitor.timer.t |
|---|
| 183 | print "t0: %s" % monitor.timer.t0 |
|---|
| 184 | monitor.timer.stamp = False |
|---|
| 185 | print "Ran: %s seconds" % monitor.timer._t |
|---|
| 186 | monitor.timer.stamp = True |
|---|
| 187 | print "Completed: %s" % (monitor.timer._t + monitor.timer.t0) |
|---|
| 188 | |
|---|
| 189 | # EOF |
|---|