We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Under the Hood: Objects, Memory, Speed step 29 of 35
hot_functions: the column you sort by is the answer you get
Profile a workload with three plausible culprits and rank them — once by
tottime and once by cumtime — so the difference between the two answers is
visible rather than theoretical.
def hot_functions(fn: Callable[[], None], *, top: int, sort: str) -> list[str]: ...
Run fn under a profiler, keep only the functions whose name starts with
_step_, sort descending by inlinetime when sort == "tottime" and by
totaltime otherwise, break ties by name ascending, and return the top top
names.
The provided driver calls four things:
| function | shape |
|---|---|
_step_tiny |
trivial body, called 500,000 times |
_step_join |
one call, a genuinely expensive nested loop |
_step_rare |
one call, moderately expensive |
_step_wrapper |
one call, does nothing but delegate to _step_join |
The two rankings disagree, and that is the entire lesson. By tottime,
_step_wrapper is last, where it belongs — it does no work. By cumtime it
ranks second, above the function that is actually slow, because a wrapper’s
cumulative time is its callee’s cumulative time. Sorting by cumulative and
reading the top rows is the standard way to spend an afternoon optimising a
decorator.
Two implementation notes.
Use profiler.getstats(), not pstats.Stats(...).stats. The latter is a
raw dict of tuples whose layout is folklore (index 2 is tottime, index 3 is
cumtime) and it is not in typeshed, so mypy --strict rejects it.
getstats() returns entries with named, typed fields: callcount,
inlinetime (= tottime), totaltime (= cumtime), and code, which is a
CodeType for Python functions and a str for built-ins — so narrow it with
isinstance before reading co_name.
Import version-tolerantly. PEP 799 moves the deterministic profiler to
profiling.tracing in 3.15, keeping cProfile as a permanent alias. A
sys.version_info gate is the right shape, because mypy prunes the branch that
does not apply to your configured python_version — a try/except ImportError
is opaque to the checker and it will complain about the module it cannot find.
And the caveat worth carrying out of this exercise: the docs say the profilers
are “not for benchmarking purposes”, and that they instrument Python but not
C, so C code looks faster than it is. A profile tells you the shape of where
time goes; timeit tells you whether your fix helped.
Your submission must pass mypy --strict.
Loading visualization…
Stuck?
Python reference solution
Sign in to attempt this problem and reveal the reference solution.