Two tests out of the inner loop, and the suite reports its own wall time - #6
Merged
Conversation
kmoneil
force-pushed
the
se-032-measure-lane
branch
from
August 24, 2026 23:40
c357453 to
7a9bf68
Compare
kmoneil
force-pushed
the
se-033-suite-runtime
branch
from
August 24, 2026 23:41
ebb5f65 to
b78eb25
Compare
kmoneil
force-pushed
the
se-032-measure-lane
branch
from
August 25, 2026 11:33
7a9bf68 to
99fda98
Compare
test_the_table and test_the_json were 17.9s of a 58.8s suite. Each runs scripts/limits.py --quick as a subprocess and the script does real timing work, which is the point of it: --quick already skips the 100,000-item runs. Marked slow and deselected from a bare pytest. The fast, compat and sdist lanes all pass --runslow, so nothing stops running where a green result is meant to mean the suite passed, and test_regression_limits_the_script_still_ runs_in_ci asserts both ends of that. Default selection 58.8s -> 39.6s. `pytest --runslow` runs the lot at 57.6s and `pytest -m slow` runs only these two. Two cheaper-looking fixes rejected and recorded. A --both mode on limits.py would halve the cost by changing a published script's interface so a test can run faster, and that interface belongs to its readers. Reducing what --quick measures is ruled out: this repository has already fixed one flake in exactly that file caused by taking a median of three instead of a minimum of five, and a test now reads the script and asserts it still does. The suite also reports its wall time on every full run, with a 240s tripwire beside it. Four times the number it protects, deliberately: a ceiling near the measurement fails on a busy machine and gets deleted rather than investigated. It arms only for the default selection, and it has been watched failing. Claude-Session: https://claude.ai/code/session_01Esnm9mNDpqRWf4QAVHCwHo
Each of the M6 changes added its own, which reads as three release sections in a row rather than one list. Claude-Session: https://claude.ai/code/session_01Esnm9mNDpqRWf4QAVHCwHo
kmoneil
force-pushed
the
se-033-suite-runtime
branch
from
August 25, 2026 11:36
b78eb25 to
08048b7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Two tests were 17.9 s of a 58.8 s suite, which is 31%:
test_limits.py::TestTheScriptRuns::test_the_tabletest_limits.py::TestTheScriptRuns::test_the_jsonBoth run
scripts/limits.py --quickas a subprocess. The script does real timing work, which is the point of it, and--quickalready skips the 100,000-item runs. They differ only in output format:--jsonemits JSON instead of the table, so neither invocation can serve both.The suite was inside its budget with no headroom:
CLAUDE.mdasks for local feedback under a minute and 58.00 s is under a minute by two seconds. A slow suite changes engineering behaviour long before it fails a gate -- people stop running it, batches get larger, and feedback time becomes the real constraint.Before and after, same machine
--runslowThe "after" rows carry 135 more tests, because #3, #4 and #5 landed first. Like for like on one commit: the default selection is 39.6 s and the full one 57.6 s, so the two tests are still 18 s and still 31% -- they are just no longer 31% of what a developer waits for.
Marked and deselected from the inner loop; run in full wherever green has to mean something
scripts/lanes.pypasses--runslowinfast,compatandsdist.sdistwas not on the original list and should have been: it runs the shipped suite from an unpacked distribution, so without the flag a lane that exists to prove the distribution is self-testing would have quietly stopped running two of its tests. Verified by running the lane: 2,350 passed, 18 skipped.test_regression_limits_the_script_still_runs_in_ciasserts both ends -- the lane's command carries the flag and CI invokes the lane. Either alone would pass while the tests stopped running. A marker that quietly stopped running in CI would be strictly worse than the ten seconds it saved.pytest --runslowruns the lot;pytest -m slowruns only these two.Deselected rather than skipped
A skip is a line of output per test claiming something was considered and not done. A deselection is one number in the summary saying the selection was smaller, which is what actually happened. It also leaves an explicit
-m slowworking without--runslow, because a marker expression is a request rather than a default.Two cheaper-looking fixes, rejected and recorded
Adding a
--bothmode toscripts/limits.pyso one invocation serves both tests halves the cost, and means changing a published script's command line so that a test can run faster. That is the wrong way round: the script is documented indocs/performance.mdas the thing a reader runs to reproduce the table on their own machine, and its interface belongs to them.Reducing what
--quickmeasures is ruled out. Cutting sample counts is how a measurement becomes a flake, and this repository has already fixed one flake in exactly that file caused by taking a median of three instead of a minimum of five.test_regression_limits_the_samples_were_not_quietly_reducednow reads the script and asserts both the count and themin, so it cannot come back through a performance change.Coverage is unchanged, and that is measured
99.65% line on the default selection, identical to the number with both tests selected. They run the script as a subprocess, which coverage does not trace, so they contributed no
src/coverage to begin with.The suite reports its own wall time now
Printed on every full run, with a 240 s tripwire beside it -- roughly four times the number it protects. A ceiling near the measurement fails on a busy machine, and a check that fails for a reason nobody can act on gets deleted rather than investigated. What this catches is somebody adding a test that takes a minute.
It arms only for the default selection:
-k,-mand a path argument all disarm it, because a subset is faster by construction and timing one against a whole-suite ceiling would be measuring nothing.It has been watched failing.
test_the_runtime_tripwire_can_actually_failcalls the hook with the clock set ten thousand seconds in the past and asserts the exit status changes.Regression battery
test_regression_limits_the_script_still_runs_in_citest_regression_limits_the_marked_tests_are_the_two_that_were_measured-- beyond the plan. A marker that spreads takes coverage out of the inner loop a test at a time and nothing else would notice.test_regression_limits_the_samples_were_not_quietly_reducedtest_the_runtime_tripwire_is_loose_enough_not_to_be_noise,..._can_actually_fail,..._stays_quiet_for_a_subset,..._reports_the_time_even_when_it_passesWhat this is not
A licence to speed up the suite generally. The other 2,412 tests run in about 40 s, which is 17 ms each. The three next-slowest are load-bearing and they stay: a denial-of-service regression test that has to do real work to prove anything, and two differential tests that generate expressions across the whole allowlist.
Checks
ruff check,ruff format --check,mypy --strictcleansdistlane run locally and passing from the distribution with the flag