3 """Tool for measuring execution time of small code snippets.
5 This module avoids a number of common traps for measuring execution
6 times. See also Tim Peters' introduction to the Algorithms chapter in
7 the Python Cookbook, published by O'Reilly.
9 Library usage: see the Timer class.
12 python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-h] [statement]
15 -n/--number N: how many times to execute 'statement' (default: see below)
16 -r/--repeat N: how many times to repeat the timer (default 3)
17 -s/--setup S: statement to be executed once initially (default 'pass')
18 -t/--time: use time.time() (default on Unix)
19 -c/--clock: use time.clock() (default on Windows)
20 -v/--verbose: print raw timing results; repeat for more digits precision
21 -h/--help: print this usage message and exit
22 statement: statement to be timed (default 'pass')
24 A multi-line statement may be given by specifying each line as a
25 separate argument; indented lines are possible by enclosing an
26 argument in quotes and using leading spaces. Multiple -s options are
29 If -n is not given, a suitable number of loops is calculated by trying
30 successive powers of 10 until the total time is at least 0.2 seconds.
32 The difference in default timer function is because on Windows,
33 clock() has microsecond granularity but time()'s granularity is 1/60th
34 of a second; on Unix, clock() has 1/100th of a second granularity and
35 time() is much more precise. On either platform, the default timer
36 functions measure wall clock time, not the CPU time. This means that
37 other processes running on the same computer may interfere with the
38 timing. The best thing to do when accurate timing is necessary is to
39 repeat the timing a few times and use the best time. The -r option is
40 good for this; the default of 3 repetitions is probably enough in most
41 cases. On Unix, you can use clock() to measure CPU time.
43 Note: there is a certain baseline overhead associated with executing a
44 pass statement. The code here doesn't try to hide it, but you should
45 be aware of it. The baseline overhead can be measured by invoking the
46 program without arguments.
48 The baseline overhead differs between Python versions! Also, to
49 fairly compare older Python versions to Python 2.3, you may want to
50 use python -O for the older versions to avoid timing SET_LINENO
70 # Must be an older Python version (see timeit() below)
77 dummy_src_name = "<timeit-src>"
78 default_number = 1000000
81 if sys.platform == "win32":
82 # On Windows, the best timer is time.clock()
83 default_timer = time.clock
85 # On most other platforms the best timer is time.time()
86 default_timer = time.time
88 # Don't change the indentation of the template; the reindent() calls
89 # in Timer.__init__() depend on setup being indented 4 spaces and stmt
90 # being indented 8 spaces.
92 def inner(_it, _timer):
101 def reindent(src, indent):
102 """Helper to reindent a multi-line statement."""
103 return string.replace(src, "\n", "\n" + " "*indent)
106 """Class for timing execution speed of small code snippets.
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
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.
117 The statements may contain newlines, as long as they don't contain
118 multi-line string literals.
121 def __init__(self, stmt="pass", setup="pass", timer=default_timer):
122 """Constructor. See class doc string."""
124 stmt = reindent(stmt, 8)
125 setup = reindent(setup, 4)
126 src = template % {'stmt': stmt, 'setup': setup}
127 self.src = src # Save for traceback display
128 code = compile(src, dummy_src_name, "exec")
130 exec code in globals(), ns
131 self.inner = ns["inner"]
133 def print_exc(self, file=None):
134 """Helper to print a traceback from the timed code.
138 t = Timer(...) # outside the try/except
140 t.timeit(...) # or t.repeat(...)
144 The advantage over the standard traceback is that source lines
145 in the compiled template will be displayed.
147 The optional file argument directs where the traceback is
148 sent; it defaults to sys.stderr.
150 import linecache, traceback
151 linecache.cache[dummy_src_name] = (len(self.src),
153 self.src.split("\n"),
155 traceback.print_exc(file=file)
157 def timeit(self, number=default_number):
158 """Time 'number' executions of the main statement.
160 To be precise, this executes the setup statement once, and
161 then returns the time it takes to execute the main statement
162 a number of times, as a float measured in seconds. The
163 argument is the number of times through the loop, defaulting
164 to one million. The main statement, the setup statement and
165 the timer function to be used are passed to the constructor.
168 it = itertools.repeat(None, number)
171 gcold = gc.isenabled()
173 timing = self.inner(it, self.timer)
178 def repeat(self, repeat=default_repeat, number=default_number):
179 """Call timeit() a few times.
181 This is a convenience function that calls the timeit()
182 repeatedly, returning a list of results. The first argument
183 specifies how many times to call timeit(), defaulting to 3;
184 the second argument specifies the timer argument, defaulting
187 Note: it's tempting to calculate mean and standard deviation
188 from the result vector and report these. However, this is not
189 very useful. In a typical case, the lowest value gives a
190 lower bound for how fast your machine can run the given code
191 snippet; higher values in the result vector are typically not
192 caused by variability in Python's speed, but by other
193 processes interfering with your timing accuracy. So the min()
194 of the result is probably the only number you should be
195 interested in. After that, you should look at the entire
196 vector and apply common sense rather than statistics.
199 for i in range(repeat):
200 t = self.timeit(number)
205 """Main program, used when run as a script.
207 The optional argument specifies the command line to be parsed,
208 defaulting to sys.argv[1:].
210 The return value is an exit code to be passed to sys.exit(); it
211 may be None to indicate success.
213 When an exception happens during timing, a traceback is printed to
214 stderr and the return value is 1. Exceptions at other times
215 (including the template compilation) are not caught.
221 opts, args = getopt.getopt(args, "n:s:r:tcvh",
222 ["number=", "setup=", "repeat=",
223 "time", "clock", "verbose", "help"])
224 except getopt.error, err:
226 print "use -h/--help for command line help"
228 timer = default_timer
229 stmt = string.join(args, "\n") or "pass"
230 number = 0 # auto-determine
232 repeat = default_repeat
236 if o in ("-n", "--number"):
238 if o in ("-s", "--setup"):
240 if o in ("-r", "--repeat"):
244 if o in ("-t", "--time"):
246 if o in ("-c", "--clock"):
248 if o in ("-v", "--verbose"):
250 precision = precision + 1
251 verbose = precision + 1
252 if o in ("-h", "--help"):
255 setup = string.join(setup, "\n") or "pass"
256 # Include the current directory, so that local imports work (sys.path
257 # contains the directory of this script, rather than the current
260 sys.path.insert(0, os.curdir)
261 t = Timer(stmt, setup, timer)
263 # determine number so that 0.2 <= total time < 2.0
264 for i in range(1, 10):
272 print "%d loops -> %.*g secs" % (number, precision, x)
276 r = t.repeat(repeat, number)
282 print "raw times:", string.join(map(lambda x, p=precision: "%.*g" % (p, x), r))
283 print "%d loops," % number,
284 usec = best * 1e6 / number
286 print "best of %d: %.*g usec per loop" % (repeat, precision, usec)
290 print "best of %d: %.*g msec per loop" % (repeat, precision, msec)
293 print "best of %d: %.*g sec per loop" % (repeat, precision, sec)
296 if __name__ == "__main__":