blob: bf0301e66317dcdf2459239a4f64cad2d0f56221 [file] [log] [blame]
Skip Montanarocfd55502003-04-08 19:49:40 +00001#! /usr/bin/env python
2
Guido van Rossum6e31aad2003-03-07 01:33:18 +00003"""Tool for measuring execution time of small code snippets.
Guido van Rossumb3f09d42003-03-05 23:31:58 +00004
Guido van Rossumb7ab6002003-03-06 02:32:19 +00005This module avoids a number of common traps for measuring execution
6times. See also Tim Peters' introduction to the Algorithms chapter in
7the Python Cookbook, published by O'Reilly.
Guido van Rossumb3f09d42003-03-05 23:31:58 +00008
Guido van Rossumb7ab6002003-03-06 02:32:19 +00009Library usage: see the Timer class.
Guido van Rossumb3f09d42003-03-05 23:31:58 +000010
11Command line usage:
Georg Brandl78e69572010-08-01 18:52:52 +000012 python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-h] [--] [statement]
Guido van Rossumb3f09d42003-03-05 23:31:58 +000013
14Options:
Guido van Rossumb7ab6002003-03-06 02:32:19 +000015 -n/--number N: how many times to execute 'statement' (default: see below)
Guido van Rossum0070f002003-03-15 12:25:00 +000016 -r/--repeat N: how many times to repeat the timer (default 3)
Guido van Rossum6e31aad2003-03-07 01:33:18 +000017 -s/--setup S: statement to be executed once initially (default 'pass')
Guido van Rossumb3f09d42003-03-05 23:31:58 +000018 -t/--time: use time.time() (default on Unix)
19 -c/--clock: use time.clock() (default on Windows)
Guido van Rossum0070f002003-03-15 12:25:00 +000020 -v/--verbose: print raw timing results; repeat for more digits precision
Guido van Rossume8577b72003-03-06 03:02:10 +000021 -h/--help: print this usage message and exit
Georg Brandl78e69572010-08-01 18:52:52 +000022 --: separate options from statement, use when statement starts with -
Guido van Rossumb3f09d42003-03-05 23:31:58 +000023 statement: statement to be timed (default 'pass')
Guido van Rossumb7ab6002003-03-06 02:32:19 +000024
25A multi-line statement may be given by specifying each line as a
26separate argument; indented lines are possible by enclosing an
Guido van Rossum6e31aad2003-03-07 01:33:18 +000027argument in quotes and using leading spaces. Multiple -s options are
28treated similarly.
Guido van Rossumb7ab6002003-03-06 02:32:19 +000029
30If -n is not given, a suitable number of loops is calculated by trying
31successive powers of 10 until the total time is at least 0.2 seconds.
32
33The difference in default timer function is because on Windows,
34clock() has microsecond granularity but time()'s granularity is 1/60th
35of a second; on Unix, clock() has 1/100th of a second granularity and
36time() is much more precise. On either platform, the default timer
Martin v. Löwis7bdc4842003-09-20 11:09:28 +000037functions measure wall clock time, not the CPU time. This means that
Guido van Rossumb7ab6002003-03-06 02:32:19 +000038other processes running on the same computer may interfere with the
39timing. The best thing to do when accurate timing is necessary is to
Guido van Rossum0070f002003-03-15 12:25:00 +000040repeat the timing a few times and use the best time. The -r option is
41good for this; the default of 3 repetitions is probably enough in most
42cases. On Unix, you can use clock() to measure CPU time.
Guido van Rossume8577b72003-03-06 03:02:10 +000043
44Note: there is a certain baseline overhead associated with executing a
45pass statement. The code here doesn't try to hide it, but you should
Guido van Rossum6e31aad2003-03-07 01:33:18 +000046be aware of it. The baseline overhead can be measured by invoking the
47program without arguments.
48
49The baseline overhead differs between Python versions! Also, to
50fairly compare older Python versions to Python 2.3, you may want to
51use python -O for the older versions to avoid timing SET_LINENO
52instructions.
Guido van Rossumb3f09d42003-03-05 23:31:58 +000053"""
54
Raymond Hettinger816ed1b2004-01-04 03:47:51 +000055import gc
Guido van Rossumb3f09d42003-03-05 23:31:58 +000056import sys
Guido van Rossumb3f09d42003-03-05 23:31:58 +000057import time
Guido van Rossum6e31aad2003-03-07 01:33:18 +000058try:
59 import itertools
60except ImportError:
61 # Must be an older Python version (see timeit() below)
62 itertools = None
Guido van Rossumb3f09d42003-03-05 23:31:58 +000063
64__all__ = ["Timer"]
65
Guido van Rossum538f1d82003-03-14 17:21:00 +000066dummy_src_name = "<timeit-src>"
Guido van Rossumb3f09d42003-03-05 23:31:58 +000067default_number = 1000000
Guido van Rossum0070f002003-03-15 12:25:00 +000068default_repeat = 3
Guido van Rossumb3f09d42003-03-05 23:31:58 +000069
70if sys.platform == "win32":
71 # On Windows, the best timer is time.clock()
72 default_timer = time.clock
73else:
74 # On most other platforms the best timer is time.time()
75 default_timer = time.time
76
Guido van Rossumb7ab6002003-03-06 02:32:19 +000077# Don't change the indentation of the template; the reindent() calls
78# in Timer.__init__() depend on setup being indented 4 spaces and stmt
79# being indented 8 spaces.
Guido van Rossumb3f09d42003-03-05 23:31:58 +000080template = """
Serhiy Storchaka59ea5082015-05-30 19:37:19 +030081def inner(_it, _timer%(init)s):
Guido van Rossumb3f09d42003-03-05 23:31:58 +000082 %(setup)s
Guido van Rossum538f1d82003-03-14 17:21:00 +000083 _t0 = _timer()
Guido van Rossumdd42edc2003-03-21 14:54:19 +000084 for _i in _it:
Guido van Rossumb3f09d42003-03-05 23:31:58 +000085 %(stmt)s
Guido van Rossum538f1d82003-03-14 17:21:00 +000086 _t1 = _timer()
87 return _t1 - _t0
Guido van Rossumb3f09d42003-03-05 23:31:58 +000088"""
89
90def reindent(src, indent):
Guido van Rossumb7ab6002003-03-06 02:32:19 +000091 """Helper to reindent a multi-line statement."""
Guido van Rossume05dcce2003-03-06 13:09:09 +000092 return src.replace("\n", "\n" + " "*indent)
Guido van Rossumb3f09d42003-03-05 23:31:58 +000093
Georg Brandld9bef352007-03-13 19:32:21 +000094def _template_func(setup, func):
95 """Create a timer function. Used if the "statement" is a callable."""
Raymond Hettinger6ecb1a32009-04-03 02:43:54 +000096 def inner(_it, _timer, _func=func):
Georg Brandld9bef352007-03-13 19:32:21 +000097 setup()
98 _t0 = _timer()
99 for _i in _it:
Raymond Hettinger6ecb1a32009-04-03 02:43:54 +0000100 _func()
Georg Brandld9bef352007-03-13 19:32:21 +0000101 _t1 = _timer()
102 return _t1 - _t0
103 return inner
104
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000105class Timer:
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000106 """Class for timing execution speed of small code snippets.
107
108 The constructor takes a statement to be timed, an additional
109 statement used for setup, and a timer function. Both statements
110 default to 'pass'; the timer function is platform-dependent (see
111 module doc string).
112
113 To measure the execution time of the first statement, use the
114 timeit() method. The repeat() method is a convenience to call
115 timeit() multiple times and return a list of results.
116
117 The statements may contain newlines, as long as they don't contain
118 multi-line string literals.
119 """
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000120
121 def __init__(self, stmt="pass", setup="pass", timer=default_timer):
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000122 """Constructor. See class doc string."""
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000123 self.timer = timer
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000124 ns = {}
Georg Brandld9bef352007-03-13 19:32:21 +0000125 if isinstance(stmt, basestring):
Serhiy Storchaka73c08632015-01-26 12:08:37 +0200126 # Check that the code can be compiled outside a function
127 if isinstance(setup, basestring):
128 compile(setup, dummy_src_name, "exec")
129 compile(setup + '\n' + stmt, dummy_src_name, "exec")
130 else:
131 compile(stmt, dummy_src_name, "exec")
Georg Brandld9bef352007-03-13 19:32:21 +0000132 stmt = reindent(stmt, 8)
133 if isinstance(setup, basestring):
134 setup = reindent(setup, 4)
Serhiy Storchaka59ea5082015-05-30 19:37:19 +0300135 src = template % {'stmt': stmt, 'setup': setup, 'init': ''}
Benjamin Petersonde055992009-10-09 22:05:45 +0000136 elif hasattr(setup, '__call__'):
Serhiy Storchaka59ea5082015-05-30 19:37:19 +0300137 src = template % {'stmt': stmt, 'setup': '_setup()',
138 'init': ', _setup=_setup'}
Georg Brandld9bef352007-03-13 19:32:21 +0000139 ns['_setup'] = setup
140 else:
141 raise ValueError("setup is neither a string nor callable")
142 self.src = src # Save for traceback display
143 code = compile(src, dummy_src_name, "exec")
144 exec code in globals(), ns
145 self.inner = ns["inner"]
Benjamin Petersonde055992009-10-09 22:05:45 +0000146 elif hasattr(stmt, '__call__'):
Georg Brandld9bef352007-03-13 19:32:21 +0000147 self.src = None
148 if isinstance(setup, basestring):
149 _setup = setup
150 def setup():
151 exec _setup in globals(), ns
Benjamin Petersonde055992009-10-09 22:05:45 +0000152 elif not hasattr(setup, '__call__'):
Georg Brandld9bef352007-03-13 19:32:21 +0000153 raise ValueError("setup is neither a string nor callable")
154 self.inner = _template_func(setup, stmt)
155 else:
156 raise ValueError("stmt is neither a string nor callable")
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000157
Guido van Rossum538f1d82003-03-14 17:21:00 +0000158 def print_exc(self, file=None):
159 """Helper to print a traceback from the timed code.
160
161 Typical use:
162
163 t = Timer(...) # outside the try/except
164 try:
165 t.timeit(...) # or t.repeat(...)
166 except:
167 t.print_exc()
168
169 The advantage over the standard traceback is that source lines
170 in the compiled template will be displayed.
171
172 The optional file argument directs where the traceback is
173 sent; it defaults to sys.stderr.
174 """
175 import linecache, traceback
Georg Brandld9bef352007-03-13 19:32:21 +0000176 if self.src is not None:
177 linecache.cache[dummy_src_name] = (len(self.src),
178 None,
179 self.src.split("\n"),
180 dummy_src_name)
181 # else the source is already stored somewhere else
182
Guido van Rossum538f1d82003-03-14 17:21:00 +0000183 traceback.print_exc(file=file)
184
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000185 def timeit(self, number=default_number):
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000186 """Time 'number' executions of the main statement.
187
188 To be precise, this executes the setup statement once, and
189 then returns the time it takes to execute the main statement
190 a number of times, as a float measured in seconds. The
191 argument is the number of times through the loop, defaulting
192 to one million. The main statement, the setup statement and
193 the timer function to be used are passed to the constructor.
194 """
Guido van Rossum6e31aad2003-03-07 01:33:18 +0000195 if itertools:
Guido van Rossumdd42edc2003-03-21 14:54:19 +0000196 it = itertools.repeat(None, number)
Guido van Rossum6e31aad2003-03-07 01:33:18 +0000197 else:
Guido van Rossumdd42edc2003-03-21 14:54:19 +0000198 it = [None] * number
Raymond Hettinger816ed1b2004-01-04 03:47:51 +0000199 gcold = gc.isenabled()
200 gc.disable()
Raymond Hettinger55e5e272011-07-28 23:56:38 -0700201 try:
202 timing = self.inner(it, self.timer)
203 finally:
204 if gcold:
205 gc.enable()
Raymond Hettinger816ed1b2004-01-04 03:47:51 +0000206 return timing
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000207
208 def repeat(self, repeat=default_repeat, number=default_number):
Skip Montanarofb2a6cc2003-04-08 19:40:19 +0000209 """Call timeit() a few times.
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000210
Skip Montanarofb2a6cc2003-04-08 19:40:19 +0000211 This is a convenience function that calls the timeit()
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000212 repeatedly, returning a list of results. The first argument
Skip Montanarofb2a6cc2003-04-08 19:40:19 +0000213 specifies how many times to call timeit(), defaulting to 3;
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000214 the second argument specifies the timer argument, defaulting
215 to one million.
Guido van Rossum55735412003-03-06 16:11:17 +0000216
217 Note: it's tempting to calculate mean and standard deviation
218 from the result vector and report these. However, this is not
219 very useful. In a typical case, the lowest value gives a
220 lower bound for how fast your machine can run the given code
221 snippet; higher values in the result vector are typically not
222 caused by variability in Python's speed, but by other
223 processes interfering with your timing accuracy. So the min()
224 of the result is probably the only number you should be
225 interested in. After that, you should look at the entire
226 vector and apply common sense rather than statistics.
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000227 """
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000228 r = []
229 for i in range(repeat):
230 t = self.timeit(number)
231 r.append(t)
232 return r
233
Georg Brandld9bef352007-03-13 19:32:21 +0000234def timeit(stmt="pass", setup="pass", timer=default_timer,
235 number=default_number):
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000236 """Convenience function to create Timer object and call timeit method."""
237 return Timer(stmt, setup, timer).timeit(number)
Georg Brandld9bef352007-03-13 19:32:21 +0000238
239def repeat(stmt="pass", setup="pass", timer=default_timer,
240 repeat=default_repeat, number=default_number):
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000241 """Convenience function to create Timer object and call repeat method."""
242 return Timer(stmt, setup, timer).repeat(repeat, number)
Georg Brandld9bef352007-03-13 19:32:21 +0000243
Serhiy Storchaka00132072015-01-26 11:54:32 +0200244def main(args=None, _wrap_timer=None):
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000245 """Main program, used when run as a script.
246
Serhiy Storchaka00132072015-01-26 11:54:32 +0200247 The optional 'args' argument specifies the command line to be parsed,
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000248 defaulting to sys.argv[1:].
249
250 The return value is an exit code to be passed to sys.exit(); it
251 may be None to indicate success.
Guido van Rossum538f1d82003-03-14 17:21:00 +0000252
253 When an exception happens during timing, a traceback is printed to
254 stderr and the return value is 1. Exceptions at other times
255 (including the template compilation) are not caught.
Serhiy Storchaka00132072015-01-26 11:54:32 +0200256
257 '_wrap_timer' is an internal interface used for unit testing. If it
258 is not None, it must be a callable that accepts a timer function
259 and returns another timer function (used for unit testing).
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000260 """
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000261 if args is None:
262 args = sys.argv[1:]
263 import getopt
264 try:
Guido van Rossum0070f002003-03-15 12:25:00 +0000265 opts, args = getopt.getopt(args, "n:s:r:tcvh",
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000266 ["number=", "setup=", "repeat=",
Guido van Rossum0070f002003-03-15 12:25:00 +0000267 "time", "clock", "verbose", "help"])
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000268 except getopt.error, err:
269 print err
Guido van Rossume8577b72003-03-06 03:02:10 +0000270 print "use -h/--help for command line help"
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000271 return 2
272 timer = default_timer
273 stmt = "\n".join(args) or "pass"
274 number = 0 # auto-determine
Guido van Rossum6e31aad2003-03-07 01:33:18 +0000275 setup = []
Guido van Rossum0070f002003-03-15 12:25:00 +0000276 repeat = default_repeat
277 verbose = 0
278 precision = 3
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000279 for o, a in opts:
280 if o in ("-n", "--number"):
281 number = int(a)
282 if o in ("-s", "--setup"):
Guido van Rossum6e31aad2003-03-07 01:33:18 +0000283 setup.append(a)
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000284 if o in ("-r", "--repeat"):
285 repeat = int(a)
286 if repeat <= 0:
287 repeat = 1
Guido van Rossume8577b72003-03-06 03:02:10 +0000288 if o in ("-t", "--time"):
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000289 timer = time.time
Guido van Rossume8577b72003-03-06 03:02:10 +0000290 if o in ("-c", "--clock"):
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000291 timer = time.clock
Guido van Rossum0070f002003-03-15 12:25:00 +0000292 if o in ("-v", "--verbose"):
293 if verbose:
294 precision += 1
295 verbose += 1
Guido van Rossume8577b72003-03-06 03:02:10 +0000296 if o in ("-h", "--help"):
297 print __doc__,
298 return 0
Guido van Rossum6e31aad2003-03-07 01:33:18 +0000299 setup = "\n".join(setup) or "pass"
Raymond Hettinger22952a32003-05-20 04:59:56 +0000300 # Include the current directory, so that local imports work (sys.path
301 # contains the directory of this script, rather than the current
302 # directory)
303 import os
304 sys.path.insert(0, os.curdir)
Serhiy Storchaka00132072015-01-26 11:54:32 +0200305 if _wrap_timer is not None:
306 timer = _wrap_timer(timer)
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000307 t = Timer(stmt, setup, timer)
308 if number == 0:
309 # determine number so that 0.2 <= total time < 2.0
310 for i in range(1, 10):
311 number = 10**i
Guido van Rossum538f1d82003-03-14 17:21:00 +0000312 try:
313 x = t.timeit(number)
314 except:
315 t.print_exc()
316 return 1
Guido van Rossum0070f002003-03-15 12:25:00 +0000317 if verbose:
318 print "%d loops -> %.*g secs" % (number, precision, x)
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000319 if x >= 0.2:
320 break
Guido van Rossum538f1d82003-03-14 17:21:00 +0000321 try:
322 r = t.repeat(repeat, number)
323 except:
324 t.print_exc()
325 return 1
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000326 best = min(r)
Guido van Rossum0070f002003-03-15 12:25:00 +0000327 if verbose:
328 print "raw times:", " ".join(["%.*g" % (precision, x) for x in r])
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000329 print "%d loops," % number,
330 usec = best * 1e6 / number
Guido van Rossum57172082003-10-20 23:38:28 +0000331 if usec < 1000:
332 print "best of %d: %.*g usec per loop" % (repeat, precision, usec)
333 else:
334 msec = usec / 1000
335 if msec < 1000:
336 print "best of %d: %.*g msec per loop" % (repeat, precision, msec)
337 else:
338 sec = msec / 1000
339 print "best of %d: %.*g sec per loop" % (repeat, precision, sec)
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000340 return None
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000341
342if __name__ == "__main__":
343 sys.exit(main())