You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[boxed/mutmut] Per-mutant timeout budget is parallelism-blind — full-core runs convert contention into spurious ⏰ verdicts
Summary
The per-mutant wall/CPU budget ((estimated_time_of_tests + 1) * 15 / * 30) is computed from a solo-run estimate, but mutmut run defaults to forking one child per core, all hammering the same test database and CPUs. Under that contention each child's covering set runs several times slower than the estimate assumes, so the fixed deadline converts scheduler contention into timeout verdicts.
Default parallelism, cold cache: run "finishes" in ~20 min with 616 ⏰ at ~1 s per "timeout" — the verdicts are contention artifacts, not scores.
Same tree, mutmut run --max-children 2, cold cache: 708 🎉 / 24 🙁 / 366 ⏰ in ~83 min (~96.7 % of scored mutants killed) — the residual ⏰ being the fixed-budget issue reported separately (missing call.when filter starves the estimate).
So the same code and tests score wildly differently depending only on child count — and nothing warns about it.
Compounding trap: cached ⏰ verdicts replay as final
Resume-from-cache replays previously recorded ⏰ verdicts across config generations: after changing the covering set's cost (or --max-children), a "resumed" run still reports the old timeouts. A meaningful re-score requires a cold mutants/ — worth documenting, or invalidating cached ⏰ (only ⏰) on config change.
Suggested fixes (any of)
Scale the deadline by the number of concurrent children (estimate × children is a cheap upper bound for a shared-resource suite).
Re-measure the baseline estimate AT the configured parallelism before scoring.
At minimum: document that DB-bound suites need --max-children well below core count, and that ⏰ verdicts from a differently-parallel run must not be resumed.
[boxed/mutmut] Per-mutant timeout budget is parallelism-blind — full-core runs convert contention into spurious ⏰ verdicts
Summary
The per-mutant wall/CPU budget (
(estimated_time_of_tests + 1) * 15/* 30) is computed from a solo-run estimate, butmutmut rundefaults to forking one child per core, all hammering the same test database and CPUs. Under that contention each child's covering set runs several times slower than the estimate assumes, so the fixed deadline converts scheduler contention into timeout verdicts.Measurements (6-core runner, DB-bound Django suite)
mutmut run --max-children 2, cold cache: 708 🎉 / 24 🙁 / 366 ⏰ in ~83 min (~96.7 % of scored mutants killed) — the residual ⏰ being the fixed-budget issue reported separately (missingcall.whenfilter starves the estimate).So the same code and tests score wildly differently depending only on child count — and nothing warns about it.
Compounding trap: cached ⏰ verdicts replay as final
Resume-from-cache replays previously recorded ⏰ verdicts across config generations: after changing the covering set's cost (or
--max-children), a "resumed" run still reports the old timeouts. A meaningful re-score requires a coldmutants/— worth documenting, or invalidating cached ⏰ (only ⏰) on config change.Suggested fixes (any of)
--max-childrenwell below core count, and that ⏰ verdicts from a differently-parallel run must not be resumed.Environment
timeout_checkeruses outer-loopmutant_namefor the est-lookup, causing spurious 15s timeouts for unrelated mutants when any "no tests" mutant exists #518 (wrong est-lookup key), and our separate report on thecall.whenrecording bug.