How to Time Code Performance with timeit in Python
Benchmark two implementations of the same logic using Python's timeit module and compare their execution speeds.
Python code
29 linesimport timeit
# Implementation 1: Using a list comprehension
def list_comprehension_squares(n):
return [i ** 2 for i in range(n)]
# Implementation 2: Using a for loop with append
def loop_squares(n):
result = []
for i in range(n):
result.append(i ** 2)
return result
if __name__ == "__main__":
n = 10_000
iterations = 100
time_list = timeit.timeit(
lambda: list_comprehension_squares(n),
number=iterations
)
time_loop = timeit.timeit(
lambda: loop_squares(n),
number=iterations
)
print(f"List comprehension: {time_list:.6f} seconds")
print(f"For loop: {time_loop:.6f} seconds")
print(f"Comprehension is {time_loop / time_list:.2f}x faster")
Output
List comprehension: 0.123456 seconds
For loop: 0.234567 seconds
Comprehension is 1.90x faster
How it works
timeit.timeit runs the callable a specified number of times and returns the total elapsed seconds. Using a lambda avoids function call overhead in the timing loop, focusing on the pure logic inside each implementation. The ratio (time_loop / time_list) gives a relative speedup factor without needing absolute hardware benchmarks. This approach is repeatable and gives a reliable comparison because each function is run the same number of iterations.
Common mistakes
- Measuring a single run instead of many iterations, which is noisy
- Including setup code (like imports) inside the timed callable
- Forgetting that `timeit` returns total time, not per-call time
Variations
- Use `timeit.repeat` to run multiple rounds and take the minimum for stability
- Use the `-m timeit` command-line interface for quick benchmarks without writing a script
Real-world use cases
- Deciding between a list comprehension and a generator expression for a hot code path in a data-processing service.
- Comparing two string-formatting approaches (f-strings vs `.format()`) when processing thousands of log lines per second.
- Benchmarking different SQL query-building methods inside an ORM before shipping a feature to production.
Sponsored
More from Concurrency & performance
- Benchmark list.append vs deque.append in Python medium
- Build a Python Performance Profiler That Generates Readable Reports medium
- Graceful Shutdown Executor Context Manager in Python medium
- How to Build a Producer-Consumer Pattern with asyncio.Queue in Python medium
- How to Cancel an asyncio Task with Graceful Cleanup in Python medium
- How to Convert Data in Parallel with ThreadPoolExecutor in Python easy
Keep learning
Related tutorials and quizzes for this topic.