We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Under the Hood: Objects, Memory, Speed step 26 of 35
timeit: take the minimum, and put the collector back
Two halves of an honest microbenchmark: the statistic you reduce with, and the interpreter state you measure under.
def reduce_ratio(timings_a: Sequence[float], timings_b: Sequence[float]) -> float: ...
def measure(*, repeat: int) -> dict[str, object]: ...
reduce_ratio returns min(timings_a) / min(timings_b). The starter uses
statistics.mean, which is the instinct from statistics class and is the wrong
instinct here. Timing noise is additive and one-sided — nothing makes code
run faster than it can, and a context switch, an interrupt or another process
makes it slower — so every sample is a true value plus non-negative noise and
the minimum is the best estimator of the true value. The documentation is
blunt about it: “the min() of the result is probably the only number you
should be interested in.”
measure builds a timeit.Timer around the provided probe callable,
calls autorange() to choose a loop count, then repeat(repeat=repeat, number=number),
and reports four facts:
| key | meaning |
|---|---|
"samples" |
len(timings) — must equal repeat |
"loops_ok" |
the loop count autorange chose is at least 1 |
"gc_on_during" |
whether the garbage collector was enabled while the timed statement ran |
"gc_enabled_after" |
whether it is enabled once measure returns |
probe records gc.isenabled() into a module dict every time it runs, so
gc_on_during is an observation rather than an assertion about timing — which
is the point. Timer.timeit calls gc.disable() before running the timing
function, so with a bare timeit.Timer(probe) the answer is False. The
documented workaround is to re-enable it in the setup, which runs inside
the timing function after the disable:
timeit.Timer(probe, setup="import gc; gc.enable()")
That matters whenever the thing you are measuring allocates — a parser, a serialiser, an ORM materialisation. Collection is part of the cost of allocation, and benchmarking with it off measures a program you do not deploy.
solve(timings_a, timings_b, do_measure, repeat) returns
{"ratio": <rounded to 9 dp>, "measured": <the dict above, or None>}.
Your submission must pass mypy --strict.
Stuck?
Python reference solution
Sign in to attempt this problem and reveal the reference solution.