Python's timeit module provides accurate timing of small code snippets. It runs code multiple times, accounts for garbage collection, and gives reliable performance measurements.
Command Line Usage
# Time a simple expression
python -m timeit "sum(range(100))"
# Multiple statements
python -m timeit "x = [i**2 for i in range(100)]"
# Setup code
python -m timeit -s "import math" "math.sqrt(100)"
# Specify iterations
python -m timeit -n 1000000 "1 + 1"Basic Python Usage
import timeit
# Time a simple statement
time = timeit.timeit('sum(range(100))', number=10000)
print(f"Total time: {time:.4f}s")
# Average per execution
avg = time / 10000
print(f"Average: {avg*1000:.4f}ms")With Setup Code
import timeit
setup = """
import random
data = [random.randint(0, 1000) for _ in range(1000)]
"""
# Time sorting
time = timeit.timeit('sorted(data)', setup=setup, number=1000)
print(f"Sorting 1000 elements: {time/1000*1000:.3f}ms")Timing Functions
import timeit
def method_one():
return [i**2 for i in range(100)]
def method_two():
return list(map(lambda x: x**2, range(100)))
# Time each function
t1 = timeit.timeit(method_one, number=10000)
t2 = timeit.timeit(method_two, number=10000)
print(f"List comprehension: {t1:.4f}s")
print(f"Map + lambda: {t2:.4f}s")repeat() for Better Statistics
import timeit
times = timeit.repeat(
'sum(range(100))',
number=10000,
repeat=5
)
print(f"Times: {times}")
print(f"Best: {min(times):.4f}s")
print(f"Average: {sum(times)/len(times):.4f}s")Use min() of repeated runs—it's most representative (less affected by system load).
Timer Class
import timeit
# Create reusable timer
timer = timeit.Timer(
stmt='"-".join(str(n) for n in range(100))',
setup='pass'
)
# Run once (includes setup)
single = timer.timeit(number=1)
# Run multiple times
total = timer.timeit(number=1000)
# Auto-calibrate number of runs
number, total_time = timer.autorange()
print(f"{number} iterations in {total_time:.2f}s")Comparing Approaches
import timeit
# String concatenation methods
approaches = {
'join': '"-".join(words)',
'plus': 'result = ""; result += w for w in words',
'format': '"-".join(f"{w}" for w in words)',
}
setup = 'words = ["hello", "world", "python", "test"]'
for name, stmt in approaches.items():
time = timeit.timeit(stmt, setup, number=100000)
print(f"{name}: {time:.4f}s")Using globals()
Access current namespace:
import timeit
my_list = list(range(1000))
def search_list():
return 500 in my_list
# Pass globals to access my_list and search_list
time = timeit.timeit(search_list, globals=globals(), number=10000)
print(f"Time: {time:.4f}s")Real Example: List vs Set Lookup
import timeit
setup = """
my_list = list(range(10000))
my_set = set(range(10000))
target = 5000
"""
list_time = timeit.timeit('target in my_list', setup, number=1000)
set_time = timeit.timeit('target in my_set', setup, number=1000)
print(f"List lookup: {list_time:.4f}s")
print(f"Set lookup: {set_time:.4f}s")
print(f"Set is {list_time/set_time:.0f}x faster")Timing Context Manager
Create your own for quick profiling:
import timeit
class Timer:
def __enter__(self):
self.start = timeit.default_timer()
return self
def __exit__(self, *args):
self.elapsed = timeit.default_timer() - self.start
# Usage
with Timer() as t:
result = sum(range(1000000))
print(f"Elapsed: {t.elapsed:.4f}s")Best Practices
- Use enough iterations: Small code needs many runs
- Take the minimum:
min(timeit.repeat(...))is most reliable - Disable GC carefully: Only for tight loops without allocation
- Compare fairly: Same setup, same number of iterations
- Profile first:
timeitfor micro-benchmarks,cProfilefor overall performance
Disabling Garbage Collection
For very precise measurements:
import timeit
# GC is disabled during timing by default
# To include GC overhead:
timer = timeit.Timer(
'list(range(1000))',
'gc.enable()',
globals={'gc': __import__('gc')}
)Quick One-Liner
import timeit
# Fastest way to time something
print(timeit.timeit(lambda: sum(range(100)), number=10000))Summary
timeit is the go-to for reliable micro-benchmarks:
- Runs code multiple times for statistical significance
- Disables garbage collection during timing
- Works from command line or Python code
- Use
repeat()and takemin()for best results
For profiling entire programs, use cProfile. For quick timing, timeit gets the job done.
React to this post: