Python timeit Tutorial: How to Measure Code Execution Time
- Home
- Python timeit Tutorial: How to Measure Code Execution Time
When developing Python applications, performance tuning is an indispensable step. However, if you measure code execution time using manual methods like time.time() or time.perf_counter(), the results are often noisy due to interference from system background tasks, the Garbage Collection (GC) mechanism, or system clock resolution.
To thoroughly solve this problem, Python provides the built-in timeit standard library. It is a precise performance measurement tool that automatically isolates the environment and runs experiments multiple times to provide the most realistic numbers.
timeit Instead of time.time()?When measuring the execution time of a code snippet, many developers have the habit of writing:
Python
import time
start = time.time()
# Do something
end = time.time()
print(end - start)
Limitations of this approach:
System noise: The OS might perform context switches, system updates, or disk read/writes right while the code is running, causing large discrepancies in measured time between trials.
Garbage Collector impact: Python’s garbage collector can trigger randomly during measurement, slowing down processing speed.
Clock resolution: time.time() relies on the system clock, which can be adjusted by NTP (Network Time Protocol).
Advantages of timeit:
Repeated execution: Automatically runs code thousands or millions of times to take the average or the best-case value.
Disables Garbage Collection by default: Eliminates noise caused by GC during benchmarking.
Uses the best timer: Automatically selects time.perf_counter() or time.process_time() depending on the OS to ensure the highest accuracy.
timeit in Python Codetimeit.timeit() functionThe function timeit.timeit(stmt, setup, number, globals) takes the following main parameters:
stmt (statement): The Python code snippet to measure (as a string or callable).
setup: Preparation code (variable declarations, library imports) run only once before measurement.
number: The number of times to repeat the stmt code (default is 1,000,000 times).
globals: Passes local/global variables into the measurement environment.
Example 1: Comparing List Comprehension and the map() function
Python
import timeit
# Compare the time to generate a list of squares
stmt_comprehension = "[x**2 for x in range(1000)]"
stmt_map = "list(map(lambda x: x**2, range(1000)))"
time_comp = timeit.timeit(stmt=stmt_comprehension, number=10000)
time_map = timeit.timeit(stmt=stmt_map, number=10000)
print(f"List Comprehension: {time_comp:.5f} seconds")
print(f"Map Function: {time_map:.5f} seconds")
Example 2: Measuring the execution time of a function
If you have already defined a function in your script, you can pass globals=globals() so timeit can recognize that function without writing it as a string:
Python
import timeit
def process_data():
return sum(i * i for i in range(10000))
# Measure process_data running 1,000 times
execution_time = timeit.timeit(process_data, number=1000)
print(f"Execution time: {execution_time:.6f} seconds")
timeit.repeat() for the Most Accurate ResultsInstead of measuring just a single cycle (looping number times), the timeit.repeat() function runs experiments across multiple cycles (repeats) and returns a list of results. This helps you find the fastest execution time (best-case execution time), eliminating periods slowed down by temporary CPU congestion.
Python
import timeit
setup_code = "data = list(range(10000))"
stmt_code = "5000 in data"
# Run 5 cycles, each cycle looping 1000 times
results = timeit.repeat(stmt=stmt_code, setup=setup_code, repeat=5, number=1000)
print("Cycle results:", results)
print(f"Best-case time: {min(results):.6f} seconds")
Tip: In performance benchmarking, the minimum value (
min(results)) typically reflects the true performance of the source code because it is least affected by external background tasks.
You can use timeit directly from the command-line interface without modifying your .py file:
Bash
# Compare string concatenation using join() vs string addition (+)
python -m timeit "'-'.join(str(n) for n in range(100))"
python -m timeit "s = ''; for n in range(100): s += str(n)"
The CLI result will automatically calculate the optimal number of iterations and output the average time along with the standard deviation:
Plaintext
20000 loops, best of 5: 12.4 usec per loop
timeitAvoid unnecessary global variables: Accessing global variables in Python is slower than local variables. Make sure your benchmark accurately reflects real-world variable scopes.
Do not measure I/O operations: timeit is designed for measuring CPU/RAM performance. Avoid using timeit to measure database queries, API calls, or file read/writes, as network or disk latency will completely skew the results.
Consider data scale: For algorithms with high complexity ($O(n^2)$ or $O(2^n)$), lower the number parameter appropriately (e.g., number=100 or number=10) to prevent your program from hanging.
The timeit library is a simple yet extremely powerful tool that helps Python developers evaluate and optimize their code scientifically. Choosing optimal data structures and algorithms based on empirical measurement data from timeit will make your applications run significantly faster and use resources much more efficiently.