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.