The timeit module is designed for accurately measuring the execution time of small code snippets. It can be used in three ways: directly in your Python scripts, via the command line interface, and with magic commands.
- In Python Scripts: Functions like
timeit.timeit()
andtimeit.repeat()
execute your code multiple times, providing greater precision and smoothing out variations in timing. - Via Command Line: You can also use the timeit module from the command line, which is perfect for quick performance tests or comparisons between different code snippets.
- With Magic Commands: For convenient use within interactive environments like IPython or Jupyter Notebooks, timeit offers the
%timeit
and%%timeit
magic commands. These let you directly time single lines of code or entire code cell, respectively.
Let’s explore how to use the timeit module to measure execution time, with specific examples and use cases.
timeit.timeit() Function
The timeit.timeit()
function is the most common and convenient way to accurately measure the execution time of small code snippets.
It works by running your code snippet multiple times and then returning the total time taken (in seconds) for all those executions. This repeated execution helps average out any random fluctuations on your system, leading to a more reliable and precise measurement of your code’s performance.
Syntax
timeit.timeit(stmt=’pass’, setup=’pass’, timer=<default timer>, number=1000000, globals=None)
Parameters
Parameter | Condition | Description |
statement | Optional | A string containing the Python code you want to time. Default is ‘pass’ |
setup | Optional | A string containing any code that must execute before your main statement. Commonly used for importing necessary modules or setting up variables. Default is ‘pass’. |
timer | Optional | A Timer object. The default timer will be the most accurate one available on your system. |
number | Optional | An integer specifying how many times to run your code snippet. Default is 1,000,000 (one million) |
globals | Optional | A namespace in which to execute the code. |
Basic Example
Here’s a simple example to illustrate how to use timeit.timeit()
.
The code below measures the execution time of a simple Python loop that sums up integers from 0 to 99. It uses the timeit.timeit()
function to execute the loop specified in the my_code
string 1,000,000 times (the default number of executions in timeit.timeit()
) and then prints the total time taken for these executions.
import timeit
my_code = """
total = 0
for i in range(100):
total += 1
"""
time_taken = timeit.timeit(my_code)
print("Total time taken:", time_taken)
# Total time taken: 1.729800899978727
Note that the output may differ slightly each time you run this code due to variations in your system’s background processes.
number Argument
The number
argument within the timeit.timeit()
function specifies how many times to run your code snippet. By default, it’s set to 1,000,000 (one million) to get a statistically reliable timing.
In the example below, the number
argument is set to 10, meaning the loop will be executed 10 times to measure the overall execution time.
import timeit
my_code = """
total = 0
for i in range(100):
total += 1
"""
time_taken = timeit.timeit(my_code, number=10)
print("Total time taken:", time_taken)
# Total time taken: 1.950003206729889e-05
It’s important to understand that the timeit.timeit()
function returns the total time it took to execute your code snippet the specified number of times.
To get the average execution time for a single run, you need to divide this total time by the value you set for the number
argument. This division helps you achieve a more accurate benchmark.
print("Average time per execution:", time_taken/10)
# Average time per execution: 1.950003206729889e-06
Always consider the expected execution time of your code before using the default number
value in timeit.timeit()
. Adjust it if necessary to avoid excessively long waiting times.
globals Argument
Sometimes your code snippet might rely on global variables that exist outside of the immediate code string you provide to timeit.timeit()
. This is where the globals
argument comes into play. It lets you specify a dictionary containing the necessary global variables your code needs to run.
Let’s illustrate this with an example. Suppose you have this code:
import timeit
def my_function():
total = 0
for i in range(100):
total += 1
time_taken = timeit.timeit('my_function()', number=10)
# NameError: name 'my_function' is not defined
If you try to run this, you’ll get an error because timeit.timeit()
executes your code in an isolated environment and doesn’t know about the my_function
you defined.
To fix this, let’s set the globals
argument to globals()
function. The globals()
function in Python returns a dictionary containing the current global variables. Let’s retry with this change:
import timeit
def my_function():
total = 0
for i in range(100):
total += 1
time_taken = timeit.timeit('my_function()', globals=globals(), number=10)
print("Total time taken:", time_taken)
# Total time taken: 2.0500272512435913e-05
print("Average time per execution:", time_taken/10)
# Average time per execution: 2.0500272512435913e-06
Now, timeit.timeit()
has access to my_function
through the globals dictionary and your code will execute successfully!
setup Argument
Often, the code you want to time might depend on external libraries or modules. The setup
argument in timeit.timeit()
lets you handle this. It’s a string where you place any code that needs to run once before your main code snippet is timed. The most common use of setup
is importing required modules.
Let’s look at an example. Suppose your code uses the random module:
import timeit
import random
def my_function():
total = 0
for i in range(100):
total += random.random()
time_taken = timeit.timeit('my_function()', setup='import random', globals=globals(), number=10)
print("Total time taken:", time_taken)
# Total time taken: 5.589984357357025e-05
print("Average time per execution:", time_taken/10)
# Average time per execution: 5.589984357357025e-06
In this example, the setup
argument instructs timeit.timeit()
to import the random module a single time before starting the timing process. This ensures that the time taken to import random doesn’t unfairly influence the measurement of your core code snippet.
timeit.repeat() Function
The timeit.repeat()
function is similar to timeit.timeit()
, but with an important enhancement. Instead of running your timing experiment just once, it runs it multiple times and provides a list of the execution times from each run.
This multi-trial approach is particularly useful for getting more reliable timing information. By performing multiple runs, timeit.repeat()
helps filter out inconsistencies caused by various factors such as background processes or system load.
Syntax
timeit.repeat(stmt=’pass’, setup=’pass’, timer=<default timer>, repeat=5, number=1000000, globals=None)
Parameters
Parameter | Condition | Description |
statement | Optional | A string containing the Python code you want to time. Default is ‘pass’ |
setup | Optional | A string containing any code that must execute before your main statement. Commonly used for importing necessary modules or setting up variables. Default is ‘pass’. |
timer | Optional | A Timer object. The default timer will be the most accurate one available on your system. |
repeat | Optional | An integer specifying how many times to repeat the whole timing experiment. Default is 5. |
number | Optional | An integer specifying how many times to run your code snippet. Default is 1,000,000 (one million) |
globals | Optional | A namespace in which to execute the code. |
Example
The timeit.repeat()
function shares many of its arguments with timeit.timeit()
, including statement
, setup
, timer
, number
, and globals
. These arguments work the same way as they do in timeit.timeit()
. They specify your code snippet, any setup code, the timer object, number of times to execute your code snippet, and any global variables your code needs.
The key addition in timeit.repeat()
is the repeat
argument. This argument controls how many times the entire timing experiment is repeated, giving you multiple execution measurements. The default is 5 repetitions.
Let’s revisit the example from timeit.timeit()
, but use timeit.repeat()
to run the timing experiment multiple times:
import timeit
import random
def my_function():
total = 0
for i in range(100):
total += random.random()
time_taken = timeit.repeat('my_function()', setup='import random', globals=globals(), repeat=3, number=10)
print("Total time taken:", time_taken)
# Total time taken: [5.7300087064504623e-05, 5.220016464591026e-05, 5.1999930292367935e-05]
The output is a list of timings, each in seconds. Each value in the list represents the total time it took to execute your code snippet 10 times during one measurement cycle. Since we repeated the measurement 3 times (repeat=3), you get 3 timings in the list.
Be aware that running timeit.repeat()
with high values for the number
(executions within one run) and repeat
(number of runs) arguments on time-consuming code can lead to very long execution times.
timeit Command-Line Interface
The command-line interface of the timeit module lets you conveniently time the execution of small Python code snippets directly from your terminal or command prompt. This is perfect for quick performance checks or comparing snippets without the need to open an interactive environment like a Jupyter notebook.
Syntax
When called from the command line, the following form is used:
python -m timeit [-n N] [-r N] [-u U] [-s S] [-p] [-v] [-h] [statement …]
Arguments
Argument | Condition | Description |
-n N, –number=N | Optional | How many times to execute ‘statement’ |
-r N, –repeat=N | Optional | How many times to repeat the timer (default 5) |
-s S, –setup=S | Optional | Statement to be executed once initially (default pass) |
-p, –process | Optional | Measure process time, not wallclock time, using time.process_time() instead of time.perf_counter(), which is the default |
-u, –unit=U | Optional | Specify a time unit for timer output; can select nsec, usec, msec, or sec |
-v, –verbose | Optional | Print raw timing results; repeat for more digits precision |
-h, –help | Optional | Print a short usage message and exit |
statement | Required | The actual Python code snippet you want to time |
Example
The following command measures the execution time for summing 100 random numbers, repeating this measurement 10 times to get a reliable average timing.
python -m timeit -n 10 "sum(range(10))"
10 loops, best of 5: 170 nsec per loop
Remember, if your code includes multiple lines, surround it with triple quotes (""" your_code """
).
python -m timeit -n 100 -s "import random" """total = 0; for i in range(100): total += random.random()"""
100 loops, best of 5: 10 nsec per loop
%timeit and %%timeit Commands
Within interactive Python environments like Jupyter Notebook or IPython, the %timeit
and %%timeit
magic commands offer a convenient way to measure the execution time of your code.
They eliminate the need to explicitly import the timeit module and write verbose timeit.timeit()
function calls, streamlining the process of timing your code’s performance.
%timeit
This magic command is designed to measure the execution time of single lines of Python code.
To use it, simply type %timeit
followed by your code snippet. For example, let’s see how long it takes to calculate the sum of numbers from 0 to 9:
In [1]: %timeit total = sum(range(10))
409 ns ± 0.462 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit
automatically determines the number of repetitions and loops to ensure accurate results while minimizing the execution time. You can customize this behavior with various options, such as:
-n
: Controls the number of loops executed within each run.-r
: Specifies how many times the timing experiment is repeated.-o
: Uses the best (fastest) timing out of all runs.
In [1]: %timeit -r 3 -n 100 total = sum(range(10))
419 ns ± 5.07 ns per loop (mean ± std. dev. of 3 runs, 100 loops each)
%%timeit
The %%timeit
command is similar to %timeit
but is used for timing multiple lines of code in a cell.
In [1]: %%timeit
...: import random
...:
...: def my_function():
...: total = 0
...: for _ in range(10):
...: total += random.random()
...:
289 ns ± 3.07 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
The same options that apply to %timeit
also apply to %%timeit
, allowing you to customize the timing process.
In [1]: %%timeit -r 3 -n 100
...: import random
...:
...: def my_function():
...: total = 0
...: for _ in range(10):
...: total += random.random()
...:
539 ns ± 14.8 ns per loop (mean ± std. dev. of 3 runs, 100 loops each)
It’s important to remember that the %timeit
and %%timeit
magic commands are specific to IPython and Jupyter notebooks. You won’t be able to use them directly within a Python script.