Skip to main content

How to Measure Execution Time of a Function in Python (With Examples)

· 4 min read
Serhii Hrekov
software engineer, creator, artist, programmer, projects founder

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

MethodBest ForPrecisionEasy to Use
time.time()General purpose timingLow
time.perf_counter()Performance testingHigh✅✅
timeitMicro-benchmarkingVery High✅✅
cProfileProfiling function callsMedium✅✅
line_profilerLine-by-line profilingHigh❌ (extra install)
Decorators/ContextMgrReusable timing instrumentationHigh✅✅✅

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.