Skip to content

← Memory, Copies and Slow Code step 30 of 38

Medium Framework

Rank Profiled Functions by Self Time or Cumulative Time

Complete hot_functions, which profiles a function and ranks the functions it called, by self time or by cumulative time. The starter always uses cumulative time, so its self-time ranking is wrong.

What to write

hot_functions(fn, *, top, sort, timer=None) -> list[str]

  • Create a fresh Profile and run fn() exactly once under it. Disable the profiler even if fn raises, and let the error reach the caller.
  • Use Profile(timer) when the caller passes a timer, and Profile() when timer is None.
  • From profiler.getstats(), keep only the entries whose code is a CodeType and whose code.co_name starts with _step_.
  • When sort == "tottime", rank by entry.inlinetime, the self time. For any other sort value, rank by entry.totaltime, the cumulative time.
  • Put the largest time first. Break ties by name, in alphabetical order.
  • Return the names in rows[:top]. A top of 0 returns [], a top larger than the list returns every name, and a negative top slices the way Python always does.

In getstats(), code is a code object for a Python function and a string for a built-in. Check isinstance(code, CodeType) before you read co_name. In the picture below, then is the code-object branch you keep, and else is the string branch you skip.

Loading visualization…

The workload

Keep Clock, make_workload and solve as they are. solve passes a fake clock as the timer, so the results don't depend on how fast your computer is. Each _step_ function adds to that clock in its own body, and cProfile counts the added time as that function's own. The units are not seconds:

Function Calls Self time Cumulative time
_step_tiny 500 500 500
_step_join 1 20 20
_step_rare 1 10 10
_step_wrapper 1 1 21

_step_wrapper adds 1 unit itself and then calls _step_join. So its self time is 1 and its cumulative time is 21. It comes second in a cumulative ranking and last in a self-time ranking.

assert solve(2) == {
    "by_tottime": ["_step_tiny", "_step_join"],
    "by_cumtime": ["_step_tiny", "_step_wrapper"],
}

Your submission must pass mypy --strict.