blob: 38077941fe89593a53a848b0a768da43f299abbd [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#! /usr/bin/env python3
Skip Montanarocfd55502003-04-08 19:49:40 +00002
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 Brandlc9d77b22012-05-01 11:56:22 +020012 python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-p] [-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')
Georg Brandlc9d77b22012-05-01 11:56:22 +020018 -p/--process: use time.process_time() (default is time.perf_counter())
19 -t/--time: use time.time() (deprecated)
20 -c/--clock: use time.clock() (deprecated)
Guido van Rossum0070f002003-03-15 12:25:00 +000021 -v/--verbose: print raw timing results; repeat for more digits precision
Guido van Rossume8577b72003-03-06 03:02:10 +000022 -h/--help: print this usage message and exit
Georg Brandl794f5b32010-08-01 08:52:32 +000023 --: separate options from statement, use when statement starts with -
Guido van Rossumb3f09d42003-03-05 23:31:58 +000024 statement: statement to be timed (default 'pass')
Guido van Rossumb7ab6002003-03-06 02:32:19 +000025
26A multi-line statement may be given by specifying each line as a
27separate argument; indented lines are possible by enclosing an
Guido van Rossum6e31aad2003-03-07 01:33:18 +000028argument in quotes and using leading spaces. Multiple -s options are
29treated similarly.
Guido van Rossumb7ab6002003-03-06 02:32:19 +000030
31If -n is not given, a suitable number of loops is calculated by trying
32successive powers of 10 until the total time is at least 0.2 seconds.
33
Guido van Rossume8577b72003-03-06 03:02:10 +000034Note: there is a certain baseline overhead associated with executing a
Terry Jan Reedyd49af5d2013-03-15 03:04:25 -040035pass statement. It differs between versions. The code here doesn't try
36to hide it, but you should be aware of it. The baseline overhead can be
37measured by invoking the program without arguments.
Guido van Rossum6e31aad2003-03-07 01:33:18 +000038
Terry Jan Reedyd49af5d2013-03-15 03:04:25 -040039Classes:
40
41 Timer
42
43Functions:
44
45 timeit(string, string) -> float
46 repeat(string, string) -> list
47 default_timer() -> float
48
Guido van Rossumb3f09d42003-03-05 23:31:58 +000049"""
50
Raymond Hettinger816ed1b2004-01-04 03:47:51 +000051import gc
Guido van Rossumb3f09d42003-03-05 23:31:58 +000052import sys
Guido van Rossumb3f09d42003-03-05 23:31:58 +000053import time
Terry Jan Reedyd49af5d2013-03-15 03:04:25 -040054import itertools
Guido van Rossumb3f09d42003-03-05 23:31:58 +000055
Terry Jan Reedyd49af5d2013-03-15 03:04:25 -040056__all__ = ["Timer", "timeit", "repeat", "default_timer"]
Guido van Rossumb3f09d42003-03-05 23:31:58 +000057
Guido van Rossum538f1d82003-03-14 17:21:00 +000058dummy_src_name = "<timeit-src>"
Guido van Rossumb3f09d42003-03-05 23:31:58 +000059default_number = 1000000
Guido van Rossum0070f002003-03-15 12:25:00 +000060default_repeat = 3
Victor Stinnerfe98e2f2012-04-29 03:01:20 +020061default_timer = time.perf_counter
Guido van Rossumb3f09d42003-03-05 23:31:58 +000062
Antoine Pitrouef3b9ed2014-08-22 23:13:50 -040063_globals = globals
64
Guido van Rossumb7ab6002003-03-06 02:32:19 +000065# Don't change the indentation of the template; the reindent() calls
66# in Timer.__init__() depend on setup being indented 4 spaces and stmt
67# being indented 8 spaces.
Guido van Rossumb3f09d42003-03-05 23:31:58 +000068template = """
Guido van Rossumdd42edc2003-03-21 14:54:19 +000069def inner(_it, _timer):
Raymond Hettingerc800af42011-04-04 09:28:25 -070070 {setup}
Guido van Rossum538f1d82003-03-14 17:21:00 +000071 _t0 = _timer()
Guido van Rossumdd42edc2003-03-21 14:54:19 +000072 for _i in _it:
Raymond Hettingerc800af42011-04-04 09:28:25 -070073 {stmt}
Guido van Rossum538f1d82003-03-14 17:21:00 +000074 _t1 = _timer()
75 return _t1 - _t0
Guido van Rossumb3f09d42003-03-05 23:31:58 +000076"""
77
78def reindent(src, indent):
Guido van Rossumb7ab6002003-03-06 02:32:19 +000079 """Helper to reindent a multi-line statement."""
Guido van Rossume05dcce2003-03-06 13:09:09 +000080 return src.replace("\n", "\n" + " "*indent)
Guido van Rossumb3f09d42003-03-05 23:31:58 +000081
Guido van Rossumd8faa362007-04-27 19:54:29 +000082def _template_func(setup, func):
83 """Create a timer function. Used if the "statement" is a callable."""
Raymond Hettingerb646aa12009-04-03 02:45:36 +000084 def inner(_it, _timer, _func=func):
Guido van Rossumd8faa362007-04-27 19:54:29 +000085 setup()
86 _t0 = _timer()
87 for _i in _it:
Raymond Hettingerb646aa12009-04-03 02:45:36 +000088 _func()
Guido van Rossumd8faa362007-04-27 19:54:29 +000089 _t1 = _timer()
90 return _t1 - _t0
91 return inner
92
Guido van Rossumb3f09d42003-03-05 23:31:58 +000093class Timer:
Guido van Rossumb7ab6002003-03-06 02:32:19 +000094 """Class for timing execution speed of small code snippets.
95
96 The constructor takes a statement to be timed, an additional
97 statement used for setup, and a timer function. Both statements
98 default to 'pass'; the timer function is platform-dependent (see
Antoine Pitrouef3b9ed2014-08-22 23:13:50 -040099 module doc string). If 'globals' is specified, the code will be
100 executed within that namespace (as opposed to inside timeit's
101 namespace).
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000102
103 To measure the execution time of the first statement, use the
104 timeit() method. The repeat() method is a convenience to call
105 timeit() multiple times and return a list of results.
106
107 The statements may contain newlines, as long as they don't contain
108 multi-line string literals.
109 """
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000110
Antoine Pitrouef3b9ed2014-08-22 23:13:50 -0400111 def __init__(self, stmt="pass", setup="pass", timer=default_timer,
112 globals=None):
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000113 """Constructor. See class doc string."""
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000114 self.timer = timer
Antoine Pitrouef3b9ed2014-08-22 23:13:50 -0400115 local_ns = {}
116 global_ns = _globals() if globals is None else globals
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000117 if isinstance(stmt, str):
Serhiy Storchaka2bef5852015-01-26 12:09:17 +0200118 # Check that the code can be compiled outside a function
119 if isinstance(setup, str):
120 compile(setup, dummy_src_name, "exec")
121 compile(setup + '\n' + stmt, dummy_src_name, "exec")
122 else:
123 compile(stmt, dummy_src_name, "exec")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000124 stmt = reindent(stmt, 8)
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000125 if isinstance(setup, str):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000126 setup = reindent(setup, 4)
Raymond Hettingerc800af42011-04-04 09:28:25 -0700127 src = template.format(stmt=stmt, setup=setup)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200128 elif callable(setup):
Raymond Hettingerc800af42011-04-04 09:28:25 -0700129 src = template.format(stmt=stmt, setup='_setup()')
Antoine Pitrouef3b9ed2014-08-22 23:13:50 -0400130 local_ns['_setup'] = setup
Guido van Rossumd8faa362007-04-27 19:54:29 +0000131 else:
132 raise ValueError("setup is neither a string nor callable")
Antoine Pitrouef3b9ed2014-08-22 23:13:50 -0400133 self.src = src # Save for traceback display
Guido van Rossumd8faa362007-04-27 19:54:29 +0000134 code = compile(src, dummy_src_name, "exec")
Antoine Pitrouef3b9ed2014-08-22 23:13:50 -0400135 exec(code, global_ns, local_ns)
136 self.inner = local_ns["inner"]
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200137 elif callable(stmt):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000138 self.src = None
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000139 if isinstance(setup, str):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000140 _setup = setup
141 def setup():
Antoine Pitrouef3b9ed2014-08-22 23:13:50 -0400142 exec(_setup, global_ns, local_ns)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200143 elif not callable(setup):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000144 raise ValueError("setup is neither a string nor callable")
145 self.inner = _template_func(setup, stmt)
146 else:
147 raise ValueError("stmt is neither a string nor callable")
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000148
Guido van Rossum538f1d82003-03-14 17:21:00 +0000149 def print_exc(self, file=None):
150 """Helper to print a traceback from the timed code.
151
152 Typical use:
153
154 t = Timer(...) # outside the try/except
155 try:
156 t.timeit(...) # or t.repeat(...)
157 except:
158 t.print_exc()
159
160 The advantage over the standard traceback is that source lines
161 in the compiled template will be displayed.
162
163 The optional file argument directs where the traceback is
164 sent; it defaults to sys.stderr.
165 """
166 import linecache, traceback
Guido van Rossumd8faa362007-04-27 19:54:29 +0000167 if self.src is not None:
168 linecache.cache[dummy_src_name] = (len(self.src),
169 None,
170 self.src.split("\n"),
171 dummy_src_name)
172 # else the source is already stored somewhere else
173
Guido van Rossum538f1d82003-03-14 17:21:00 +0000174 traceback.print_exc(file=file)
175
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000176 def timeit(self, number=default_number):
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000177 """Time 'number' executions of the main statement.
178
179 To be precise, this executes the setup statement once, and
180 then returns the time it takes to execute the main statement
181 a number of times, as a float measured in seconds. The
182 argument is the number of times through the loop, defaulting
183 to one million. The main statement, the setup statement and
184 the timer function to be used are passed to the constructor.
185 """
Terry Jan Reedyd49af5d2013-03-15 03:04:25 -0400186 it = itertools.repeat(None, number)
Raymond Hettinger816ed1b2004-01-04 03:47:51 +0000187 gcold = gc.isenabled()
188 gc.disable()
Raymond Hettinger3a081f52011-07-29 00:02:04 -0700189 try:
190 timing = self.inner(it, self.timer)
191 finally:
192 if gcold:
193 gc.enable()
Raymond Hettinger816ed1b2004-01-04 03:47:51 +0000194 return timing
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000195
196 def repeat(self, repeat=default_repeat, number=default_number):
Skip Montanarofb2a6cc2003-04-08 19:40:19 +0000197 """Call timeit() a few times.
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000198
Skip Montanarofb2a6cc2003-04-08 19:40:19 +0000199 This is a convenience function that calls the timeit()
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000200 repeatedly, returning a list of results. The first argument
Skip Montanarofb2a6cc2003-04-08 19:40:19 +0000201 specifies how many times to call timeit(), defaulting to 3;
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000202 the second argument specifies the timer argument, defaulting
203 to one million.
Guido van Rossum55735412003-03-06 16:11:17 +0000204
205 Note: it's tempting to calculate mean and standard deviation
206 from the result vector and report these. However, this is not
207 very useful. In a typical case, the lowest value gives a
208 lower bound for how fast your machine can run the given code
209 snippet; higher values in the result vector are typically not
210 caused by variability in Python's speed, but by other
211 processes interfering with your timing accuracy. So the min()
212 of the result is probably the only number you should be
213 interested in. After that, you should look at the entire
214 vector and apply common sense rather than statistics.
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000215 """
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000216 r = []
217 for i in range(repeat):
218 t = self.timeit(number)
219 r.append(t)
220 return r
221
Guido van Rossumd8faa362007-04-27 19:54:29 +0000222def timeit(stmt="pass", setup="pass", timer=default_timer,
Antoine Pitrouef3b9ed2014-08-22 23:13:50 -0400223 number=default_number, globals=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000224 """Convenience function to create Timer object and call timeit method."""
Antoine Pitrouef3b9ed2014-08-22 23:13:50 -0400225 return Timer(stmt, setup, timer, globals).timeit(number)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000226
227def repeat(stmt="pass", setup="pass", timer=default_timer,
Antoine Pitrouef3b9ed2014-08-22 23:13:50 -0400228 repeat=default_repeat, number=default_number, globals=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000229 """Convenience function to create Timer object and call repeat method."""
Antoine Pitrouef3b9ed2014-08-22 23:13:50 -0400230 return Timer(stmt, setup, timer, globals).repeat(repeat, number)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000231
R David Murraya88da672011-03-16 17:32:27 -0400232def main(args=None, *, _wrap_timer=None):
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000233 """Main program, used when run as a script.
234
R David Murraya88da672011-03-16 17:32:27 -0400235 The optional 'args' argument specifies the command line to be parsed,
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000236 defaulting to sys.argv[1:].
237
238 The return value is an exit code to be passed to sys.exit(); it
239 may be None to indicate success.
Guido van Rossum538f1d82003-03-14 17:21:00 +0000240
241 When an exception happens during timing, a traceback is printed to
242 stderr and the return value is 1. Exceptions at other times
243 (including the template compilation) are not caught.
R David Murraya88da672011-03-16 17:32:27 -0400244
245 '_wrap_timer' is an internal interface used for unit testing. If it
246 is not None, it must be a callable that accepts a timer function
247 and returns another timer function (used for unit testing).
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000248 """
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000249 if args is None:
250 args = sys.argv[1:]
251 import getopt
252 try:
Georg Brandlc9d77b22012-05-01 11:56:22 +0200253 opts, args = getopt.getopt(args, "n:s:r:tcpvh",
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000254 ["number=", "setup=", "repeat=",
Georg Brandlc9d77b22012-05-01 11:56:22 +0200255 "time", "clock", "process",
256 "verbose", "help"])
Guido van Rossumb940e112007-01-10 16:19:56 +0000257 except getopt.error as err:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000258 print(err)
259 print("use -h/--help for command line help")
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000260 return 2
261 timer = default_timer
262 stmt = "\n".join(args) or "pass"
263 number = 0 # auto-determine
Guido van Rossum6e31aad2003-03-07 01:33:18 +0000264 setup = []
Guido van Rossum0070f002003-03-15 12:25:00 +0000265 repeat = default_repeat
266 verbose = 0
267 precision = 3
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000268 for o, a in opts:
269 if o in ("-n", "--number"):
270 number = int(a)
271 if o in ("-s", "--setup"):
Guido van Rossum6e31aad2003-03-07 01:33:18 +0000272 setup.append(a)
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000273 if o in ("-r", "--repeat"):
274 repeat = int(a)
275 if repeat <= 0:
276 repeat = 1
Guido van Rossume8577b72003-03-06 03:02:10 +0000277 if o in ("-t", "--time"):
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000278 timer = time.time
Guido van Rossume8577b72003-03-06 03:02:10 +0000279 if o in ("-c", "--clock"):
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000280 timer = time.clock
Georg Brandlc9d77b22012-05-01 11:56:22 +0200281 if o in ("-p", "--process"):
282 timer = time.process_time
Guido van Rossum0070f002003-03-15 12:25:00 +0000283 if o in ("-v", "--verbose"):
284 if verbose:
285 precision += 1
286 verbose += 1
Guido van Rossume8577b72003-03-06 03:02:10 +0000287 if o in ("-h", "--help"):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000288 print(__doc__, end=' ')
Guido van Rossume8577b72003-03-06 03:02:10 +0000289 return 0
Guido van Rossum6e31aad2003-03-07 01:33:18 +0000290 setup = "\n".join(setup) or "pass"
Raymond Hettinger22952a32003-05-20 04:59:56 +0000291 # Include the current directory, so that local imports work (sys.path
292 # contains the directory of this script, rather than the current
293 # directory)
294 import os
295 sys.path.insert(0, os.curdir)
R David Murraya88da672011-03-16 17:32:27 -0400296 if _wrap_timer is not None:
297 timer = _wrap_timer(timer)
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000298 t = Timer(stmt, setup, timer)
299 if number == 0:
300 # determine number so that 0.2 <= total time < 2.0
301 for i in range(1, 10):
302 number = 10**i
Guido van Rossum538f1d82003-03-14 17:21:00 +0000303 try:
304 x = t.timeit(number)
305 except:
306 t.print_exc()
307 return 1
Guido van Rossum0070f002003-03-15 12:25:00 +0000308 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000309 print("%d loops -> %.*g secs" % (number, precision, x))
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000310 if x >= 0.2:
311 break
Guido van Rossum538f1d82003-03-14 17:21:00 +0000312 try:
313 r = t.repeat(repeat, number)
314 except:
315 t.print_exc()
316 return 1
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000317 best = min(r)
Guido van Rossum0070f002003-03-15 12:25:00 +0000318 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000319 print("raw times:", " ".join(["%.*g" % (precision, x) for x in r]))
320 print("%d loops," % number, end=' ')
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000321 usec = best * 1e6 / number
Guido van Rossum57172082003-10-20 23:38:28 +0000322 if usec < 1000:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000323 print("best of %d: %.*g usec per loop" % (repeat, precision, usec))
Guido van Rossum57172082003-10-20 23:38:28 +0000324 else:
325 msec = usec / 1000
326 if msec < 1000:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000327 print("best of %d: %.*g msec per loop" % (repeat, precision, msec))
Guido van Rossum57172082003-10-20 23:38:28 +0000328 else:
329 sec = msec / 1000
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000330 print("best of %d: %.*g sec per loop" % (repeat, precision, sec))
Guido van Rossumb7ab6002003-03-06 02:32:19 +0000331 return None
Guido van Rossumb3f09d42003-03-05 23:31:58 +0000332
333if __name__ == "__main__":
334 sys.exit(main())