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 |
---|