mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	
		
			
	
	
		
			185 lines
		
	
	
	
		
			6.9 KiB
		
	
	
	
		
			TeX
		
	
	
	
	
	
		
		
			
		
	
	
			185 lines
		
	
	
	
		
			6.9 KiB
		
	
	
	
		
			TeX
		
	
	
	
	
	
| 
								 | 
							
								\section{\module{timeit} ---
							 | 
						||
| 
								 | 
							
								         Measure execution time of small code snippets}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\declaremodule{standard}{timeit}
							 | 
						||
| 
								 | 
							
								\modulesynopsis{Measure the execution time of small code snippets.}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\index{Benchmarking}
							 | 
						||
| 
								 | 
							
								\index{Performance}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\versionadded{2.3}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This module provides a simple way to time small bits of Python code.  It has
							 | 
						||
| 
								 | 
							
								both command line as well as callable interfaces.  It avoids a number of
							 | 
						||
| 
								 | 
							
								common traps for measuring execution times.  See also Tim Peters'
							 | 
						||
| 
								 | 
							
								introduction to the Algorithms chapter in the ``Python Cookbook'', published
							 | 
						||
| 
								 | 
							
								by O'Reilly.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The module interface defines the following public class:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\begin{classdesc}{Timer}{\optional{stmt='pass'
							 | 
						||
| 
								 | 
							
											 \optional{, setup='pass'
							 | 
						||
| 
								 | 
							
											 \optional{, timer=<timer function>}}}}
							 | 
						||
| 
								 | 
							
								Class for timing execution speed of small code snippets.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The constructor takes a statement to be timed, an additional statement used
							 | 
						||
| 
								 | 
							
								for setup, and a timer function.  Both statements default to 'pass'; the
							 | 
						||
| 
								 | 
							
								timer function is platform-dependent (see the module doc string).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								To measure the execution time of the first statement, use the timeit()
							 | 
						||
| 
								 | 
							
								method.  The repeat() method is a convenience to call timeit() multiple
							 | 
						||
| 
								 | 
							
								times and return a list of results.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The statements may contain newlines, as long as they don't contain
							 | 
						||
| 
								 | 
							
								multi-line string literals.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\begin{methoddesc}{print_exc}{\optional{file=None}}
							 | 
						||
| 
								 | 
							
								Helper to print a traceback from the timed code.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Typical use:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\begin{verbatim}
							 | 
						||
| 
								 | 
							
								    t = Timer(...)       # outside the try/except
							 | 
						||
| 
								 | 
							
								    try:
							 | 
						||
| 
								 | 
							
								        t.timeit(...)    # or t.repeat(...)
							 | 
						||
| 
								 | 
							
								    except:
							 | 
						||
| 
								 | 
							
								        t.print_exc()
							 | 
						||
| 
								 | 
							
								\end{verbatim}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The advantage over the standard traceback is that source lines in the
							 | 
						||
| 
								 | 
							
								compiled template will be displayed.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The optional file argument directs where the traceback is sent; it defaults
							 | 
						||
| 
								 | 
							
								to \code{sys.stderr}.
							 | 
						||
| 
								 | 
							
								\end{methoddesc}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\begin{methoddesc}{repeat}{\optional{repeat=3\optional{, number=1000000}}}
							 | 
						||
| 
								 | 
							
								Call \method{timeit()} a few times.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This is a convenience function that calls the \method{timeit()} repeatedly,
							 | 
						||
| 
								 | 
							
								returning a list of results.  The first argument specifies how many times to
							 | 
						||
| 
								 | 
							
								call \function{timeit()}.  The second argument specifies the \code{number}
							 | 
						||
| 
								 | 
							
								argument for \function{timeit()}.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Note: it's tempting to calculate mean and standard deviation from the result
							 | 
						||
| 
								 | 
							
								vector and report these.  However, this is not very useful.  In a typical
							 | 
						||
| 
								 | 
							
								case, the lowest value gives a lower bound for how fast your machine can run
							 | 
						||
| 
								 | 
							
								the given code snippet; higher values in the result vector are typically not
							 | 
						||
| 
								 | 
							
								caused by variability in Python's speed, but by other processes interfering
							 | 
						||
| 
								 | 
							
								with your timing accuracy.  So the \function{min()} of the result is
							 | 
						||
| 
								 | 
							
								probably the only number you should be interested in.  After that, you
							 | 
						||
| 
								 | 
							
								should look at the entire vector and apply common sense rather than
							 | 
						||
| 
								 | 
							
								statistics.
							 | 
						||
| 
								 | 
							
								\end{methoddesc}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\begin{methoddesc}{timeit}{\optional{number=1000000}}
							 | 
						||
| 
								 | 
							
								Time \code{number} executions of the main statement.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								To be precise, this executes the setup statement once, and then returns the
							 | 
						||
| 
								 | 
							
								time it takes to execute the main statement a number of times, as a float
							 | 
						||
| 
								 | 
							
								measured in seconds.  The argument is the number of times through the loop,
							 | 
						||
| 
								 | 
							
								defaulting to one million.  The main statement, the setup statement and the
							 | 
						||
| 
								 | 
							
								timer function to be used are passed to the constructor.
							 | 
						||
| 
								 | 
							
								\end{methoddesc}
							 | 
						||
| 
								 | 
							
								\end{classdesc}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\subsection{Command Line Interface}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								When called as a program from the command line, the following form is used:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\begin{verbatim}
							 | 
						||
| 
								 | 
							
								    python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-h] [statement ...]
							 | 
						||
| 
								 | 
							
								\end{verbatim}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								where the following options are understood:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\begin{description}
							 | 
						||
| 
								 | 
							
								\item[-n N/--number=N] how many times to execute 'statement'
							 | 
						||
| 
								 | 
							
								\item[-r N/--repeat=N] how many times to repeat the timer (default 3)
							 | 
						||
| 
								 | 
							
								\item[-s S/--setup=S] statement to be executed once initially (default
							 | 
						||
| 
								 | 
							
								'pass')
							 | 
						||
| 
								 | 
							
								\item[-t/--time] use time.time() (default on all platforms but Windows)
							 | 
						||
| 
								 | 
							
								\item[-c/--clock] use time.clock() (default on Windows)
							 | 
						||
| 
								 | 
							
								\item[-v/--verbose] print raw timing results; repeat for more digits
							 | 
						||
| 
								 | 
							
								precision 
							 | 
						||
| 
								 | 
							
								\item[-h/--help] print a short usage message and exit
							 | 
						||
| 
								 | 
							
								\end{description}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								A multi-line statement may be given by specifying each line as a separate
							 | 
						||
| 
								 | 
							
								statement argument; indented lines are possible by enclosing an argument in
							 | 
						||
| 
								 | 
							
								quotes and using leading spaces.  Multiple -s options are treated similarly.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If -n is not given, a suitable number of loops is calculated by trying
							 | 
						||
| 
								 | 
							
								successive powers of 10 until the total time is at least 0.2 seconds.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The default timer function is platform dependent.  On Windows, clock() has
							 | 
						||
| 
								 | 
							
								microsecond granularity but time()'s granularity is 1/60th of a second; on
							 | 
						||
| 
								 | 
							
								Unix, clock() has 1/100th of a second granularity and time() is much more
							 | 
						||
| 
								 | 
							
								precise.  On either platform, the default timer functions measures wall
							 | 
						||
| 
								 | 
							
								clock time, not the CPU time.  This means that other processes running on
							 | 
						||
| 
								 | 
							
								the same computer may interfere with the timing.  The best thing to do when
							 | 
						||
| 
								 | 
							
								accurate timing is necessary is to repeat the timing a few times and use the
							 | 
						||
| 
								 | 
							
								best time.  The -r option is good for this; the default of 3 repetitions is
							 | 
						||
| 
								 | 
							
								probably enough in most cases.  On Unix, you can use clock() to measure CPU
							 | 
						||
| 
								 | 
							
								time.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Note: there is a certain baseline overhead associated with executing a pass
							 | 
						||
| 
								 | 
							
								statement.  The code here doesn't try to hide it, but you should be aware of
							 | 
						||
| 
								 | 
							
								it.  The baseline overhead can be measured by invoking the program without
							 | 
						||
| 
								 | 
							
								arguments.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The baseline overhead differs between Python versions!  Also, to fairly
							 | 
						||
| 
								 | 
							
								compare older Python versions to Python 2.3, you may want to use python -O
							 | 
						||
| 
								 | 
							
								for the older versions to avoid timing SET_LINENO instructions.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\subsection{Examples}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Here are two example sessions (one using the command line, one using the
							 | 
						||
| 
								 | 
							
								module interface) that compare the cost of using \function{hasattr()}
							 | 
						||
| 
								 | 
							
								vs. try/except to test for missing and present object attributes.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\begin{verbatim}
							 | 
						||
| 
								 | 
							
								\% timeit.py 'try:' '  str.__nonzero__' 'except AttributeError:' '  pass'
							 | 
						||
| 
								 | 
							
								100000 loops, best of 3: 15.7 usec per loop
							 | 
						||
| 
								 | 
							
								\% timeit.py 'if hasattr(str, "__nonzero__"): pass'
							 | 
						||
| 
								 | 
							
								100000 loops, best of 3: 4.26 usec per loop
							 | 
						||
| 
								 | 
							
								\% timeit.py 'try:' '  int.__nonzero__' 'except AttributeError:' '  pass'
							 | 
						||
| 
								 | 
							
								1000000 loops, best of 3: 1.43 usec per loop
							 | 
						||
| 
								 | 
							
								\% timeit.py 'if hasattr(int, "__nonzero__"): pass'
							 | 
						||
| 
								 | 
							
								100000 loops, best of 3: 2.23 usec per loop
							 | 
						||
| 
								 | 
							
								\end{verbatim}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\begin{verbatim}
							 | 
						||
| 
								 | 
							
								>>> import timeit
							 | 
						||
| 
								 | 
							
								>>> s = """\
							 | 
						||
| 
								 | 
							
								... try:
							 | 
						||
| 
								 | 
							
								...   str.__nonzero__
							 | 
						||
| 
								 | 
							
								... except AttributeError:
							 | 
						||
| 
								 | 
							
								...   pass
							 | 
						||
| 
								 | 
							
								... """
							 | 
						||
| 
								 | 
							
								>>> t = timeit.Timer(stmt=s)
							 | 
						||
| 
								 | 
							
								>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)
							 | 
						||
| 
								 | 
							
								17.09 usec/pass
							 | 
						||
| 
								 | 
							
								>>> s = """\
							 | 
						||
| 
								 | 
							
								... if hasattr(str, '__nonzero__'): pass
							 | 
						||
| 
								 | 
							
								... """
							 | 
						||
| 
								 | 
							
								>>> t = timeit.Timer(stmt=s)
							 | 
						||
| 
								 | 
							
								>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)
							 | 
						||
| 
								 | 
							
								4.85 usec/pass
							 | 
						||
| 
								 | 
							
								>>> s = """\
							 | 
						||
| 
								 | 
							
								... try:
							 | 
						||
| 
								 | 
							
								...   int.__nonzero__
							 | 
						||
| 
								 | 
							
								... except AttributeError:
							 | 
						||
| 
								 | 
							
								...   pass 
							 | 
						||
| 
								 | 
							
								... """
							 | 
						||
| 
								 | 
							
								>>> t = timeit.Timer(stmt=s)
							 | 
						||
| 
								 | 
							
								>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)
							 | 
						||
| 
								 | 
							
								1.97 usec/pass
							 | 
						||
| 
								 | 
							
								>>> s = """\
							 | 
						||
| 
								 | 
							
								... if hasattr(int, '__nonzero__'): pass
							 | 
						||
| 
								 | 
							
								... """
							 | 
						||
| 
								 | 
							
								>>> t = timeit.Timer(stmt=s)
							 | 
						||
| 
								 | 
							
								>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)
							 | 
						||
| 
								 | 
							
								3.15 usec/pass
							 | 
						||
| 
								 | 
							
								\end{verbatim}
							 |