Profiling with cProfile
Timing says how slow a program is. A profiler says where the time goes: it records every function call, how often each function ran, and the time spent in it.
import cProfile
import pstats
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
prof = cProfile.Profile()
prof.runcall(fib, 20)
stats = pstats.Stats(prof)
stats.sort_stats("cumulative")
stats.print_stats(3)Reading the table
ncallsis how many times a function ran.21891/1means 21891 calls in all, only one of them from outside, becausefibis recursive.tottimeis time inside the function itself.cumtimeadds the functions it called.- Sort by
cumulativeto follow the slow path, and bytottimeto find the hot spot.
A call count that grows much faster than the input often tells you more than any timing. Here 21891 calls for fib(20) reveal repeated work that a cache removes. On a desktop, python -m cProfile -s cumtime app.py profiles a whole script.
Your task
Write count_calls(func, *args) that runs func(*args) under a cProfile.Profile and returns (result, calls), where calls maps the name of each Python function that ran to its total number of calls as an int. Leave out built-ins, whose file_name in get_stats_profile() is "~".
The explanation opens here once every check passes.