Measure elapsed time in Python
Compare Python timing functions, measure elapsed work with perf_counter, and avoid confusing nanosecond units with clock resolution.
Use time.perf_counter() to measure how long an operation takes. Subtract a reading taken before the work from one taken afterward; the difference includes time spent waiting or sleeping.
Time a block of code
import time
start = time.perf_counter()
result = sum(range(1_000_000))
elapsed = time.perf_counter() - start
print(f"Elapsed: {elapsed:.4f} seconds")
The clock's reference point is unspecified. Its readings are useful as differences, not as dates or timestamps for logs.
Choose a clock for the task
| Function | What it measures | Typical use |
|---|---|---|
perf_counter() |
A high-resolution performance counter, including sleep | Elapsed operation time and small benchmarks |
monotonic() |
Time from a clock that cannot go backward | Deadlines and timeouts |
time() |
Seconds since the Unix epoch | Wall-clock timestamps |
process_time() |
Process CPU time, excluding sleep | CPU work rather than end-to-end latency |
time.time() can jump when the system clock changes, so subtracting its readings is a poor choice for reliable durations. monotonic() and perf_counter() are not a universal low-precision/high-precision pair: CPython 3.13 and later use the same clock for both. Inspect the actual resolution with time.get_clock_info("perf_counter").resolution.
For timeout calculations, use the same monotonic clock for both readings:
started = time.monotonic()
# Perform the operation here.
elapsed = time.monotonic() - started
Wrap repeated measurements
import functools
import time
def timing(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
try:
return func(*args, **kwargs)
finally:
print(f"{func.__name__}: {time.perf_counter() - start:.4f}s")
return wrapper
@timing
def slow_function():
time.sleep(0.01)
The finally block records elapsed time even if the function raises. This wrapper is for synchronous functions. To time a coroutine's execution, measure around await, not just around creating its coroutine object.
FAQ
Does perf_counter_ns() guarantee nanosecond accuracy? No. It returns integer nanoseconds and avoids floating-point precision loss; hardware and operating-system clock resolution still apply.
How do I find a slow line? cProfile reports function-level statistics. Use a line profiler when you need line-level measurements. For small implementation comparisons, use repeated timeit runs rather than trusting one elapsed-time sample.
References
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan