We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Under the Hood: Objects, Memory, Speed step 19 of 35
find_growth: measure retention, and stop the tracer on every path
Implement the measurement that distinguishes “this function allocates” from “this function leaks”.
def find_growth(fn: Callable[[], None], *, iterations: int) -> int: ...
Return the net traced bytes retained by running fn iterations times:
start the tracer, warm up with one call, snapshot, run iterations times,
snapshot, and sum size_diff over after.compare_to(before, "lineno").
The tracer must be stopped on every path, including when fn raises —
and the exception must still propagate. tracemalloc is global process
state; a tracer left running silently changes the overhead of every
subsequent measurement in the process, which is a genuinely nasty way to
spend an afternoon.
Three workloads are provided:
| name | behaviour |
|---|---|
"leaks" |
appends a 1,000-element list to a module-level SINK |
"churns" |
allocates a 1,000-element list and immediately releases it |
"explodes" |
raises ValueError |
solve(workload, iterations) calls find_growth at iterations and then
again at 2 * iterations, clearing SINK between the two so the runs are
independent, and returns:
{"grew": bool, "scaled": bool, "raised": str, "tracing_stopped": bool}
where grew is “first measurement exceeded 100 KB”, scaled is “it grew and
doubling the iteration count grew it by at least 1.5x”, raised is "" or
"ValueError", and tracing_stopped reports not tracemalloc.is_tracing()
after everything.
Why the warm-up matters. First-call allocations — an import, a compiled regex, a lazily built cache, a connection — are one-time costs. Snapshot before them and they dominate the diff, so a function that allocates 2 MB once and nothing thereafter looks exactly like a leak. One warm-up call removes the entire category.
Why the doubling matters. Growth that scales with the iteration count is a leak. Growth that does not is what a call costs. Measuring at one N cannot tell them apart, and that distinction is the whole reason anyone runs this.
Your submission must pass mypy --strict.
Stuck?
Python reference solution
Sign in to attempt this problem and reveal the reference solution.