cProfile records executed calls; exact elapsed time is not a stable test assertion.
Python cProfile: inspect call counts without asserting timing
Operation contract
A settlement calculation runs three times under one profiler. The resulting Stats object is queried for the function's call count, while the last business total is asserted independently. This verifies instrumentation without printing timing numbers that change with hardware and process load.
Failure boundary
Profiling adds overhead and can change scheduling. A deterministic call count says nothing about production latency, input-size growth, or memory allocation. For a bottleneck decision, profile representative data and inspect cumulative time across the actual call graph, then benchmark the revised implementation separately.
Working program
import cProfile
import pstats
def net_total(amounts):
return sum(amount - 3 for amount in amounts)
profile = cProfile.Profile()
for _ in range(3):
last_total = profile.runcall(net_total, (47, 48, 49))
statistics = pstats.Stats(profile)
calls = sum(record[1] for key, record in statistics.stats.items()
if key[2] == "net_total")
print("last_total", last_total)
print("calls", calls)Output
last_total 135
calls 3Costs and limits
Instrumentation records function events and adds runtime overhead. Its storage grows with the number of distinct recorded call sites, not with this printed call count alone.
Common Mistakes
- Do not assert exact profile seconds in a portable test.
- A call count is not a latency measurement.
- Small synthetic inputs can hide the expensive path in production.
