Skip to main content

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

ยท 6 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.