How to Measure Execution Time of a Function in Python (With Examples)
Measuring how long your Python code takes to run is a critical skill for performance optimization, profiling, or benchmarking different approaches to solving a problem. Python offers many tools for tracking the execution time of a function - from simple built-in methods to full-blown profilers.
In this guide, we will explore multiple methods with code examples to help you choose the right one for your use case.
1. Using time.time()​
This is one of the simplest and most accessible ways to measure elapsed time.
import time
def my_function():
time.sleep(1)
start = time.time()
my_function()
end = time.time()
print(f"Execution time: {end - start:.4f} seconds")
Simple and quick Less accurate on very fast functions
Using time.perf_counter()​
For higher precision and accuracy, especially for short-running functions.
import time
def fast_function():
return sum(range(1000))
start = time.perf_counter()
fast_function()
end = time.perf_counter()
print(f"Execution time: {end - start:.6f} seconds")
Recommended for performance benchmarks High precision timer (includes sleep time)
Using time.process_time()​
Focuses only on the CPU execution time (does not count sleep or I/O waits).
import time
def cpu_bound_task():
for _ in range(10**6):
_ = 1 + 1
start = time.process_time()
cpu_bound_task()
end = time.process_time()
print(f"CPU execution time: {end - start:.6f} seconds")
Good for CPU-bound tasks Not suitable for I/O or async tasks
Using timeit Module (Best for Benchmarking)​
timeit automatically handles setup and repeat runs for statistical accuracy. If you want you can use it from code or CLI, here is code version:
def example():
return sum(range(100))
execution_time = timeit.timeit(example, number=10000)
print(f"Average execution time over 10,000 runs: {execution_time:.6f} seconds")
CLI version:
python -m timeit "sum(range(100))"
Best tool for comparing functions Automatically disables garbage collection
Using a Context Manager​
You can define your own timer context:
import time
class Timer:
def __enter__(self):
self.start = time.perf_counter()
return self
def __exit__(self, *args):
self.end = time.perf_counter()
self.interval = self.end - self.start
print(f"Execution time: {self.interval:.6f} seconds")
with Timer():
sum(range(100000))
Clean syntax Reusable across your codebase
Using a Decorator​
Decorators are perfect for reusing timing logic across many functions.
import time
from functools import wraps
def timing_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
print(f"{func.__name__} took {end - start:.6f} seconds")
return result
return wrapper
@timing_decorator
def slow_function():
time.sleep(1.5)
slow_function()
DRY and expressive Works on many functions
Using cProfile (Advanced Profiling)​
If you need a detailed performance breakdown:
import cProfile
def compute():
sum([i ** 2 for i in range(10000)])
cProfile.run('compute()')
Good for profiling large applications Includes function call stats
Using line_profiler (Third-party Tool)​
Install it first:
pip install line_profiler
Then with python:
@profile
def heavy_function():
for i in range(10000):
x = i **2
y = x** 0.5
Run with cli:
kernprof -l -v my_script.py
Line-by-line execution time External dependency
Using tracemalloc for Memory + Time Insights​
Bonus if you want to track memory usage + execution time:
import time
import tracemalloc
tracemalloc.start()
start = time.perf_counter()
[sum(range(1000)) for _ in range(10000)]
end = time.perf_counter()
current, peak = tracemalloc.get_traced_memory()
print(f"Time: {end - start:.6f} sec, Peak Memory: {peak / 10**6:.2f} MB")
tracemalloc.stop()
Conclusion​
| Method | Best For | Precision | Easy to Use |
|---|---|---|---|
time.time() | General purpose timing | Low | âś… |
time.perf_counter() | Performance testing | High | âś…âś… |
timeit | Micro-benchmarking | Very High | âś…âś… |
cProfile | Profiling function calls | Medium | âś…âś… |
line_profiler | Line-by-line profiling | High | ❌ (extra install) |
| Decorators/ContextMgr | Reusable timing instrumentation | High | âś…âś…âś… |
Further Reading​
You now have a full toolbox to choose from when measuring Python function execution times. Use the simplest for quick debugging, or go with profilers for full diagnostics.
