Repository navigation
fix(xtest): fail benchmark cells whose build hangs instead of skipping - #685
Draft
dmihalcik-virtru wants to merge 1 commit into
Draft
dmihalcik-virtru wants to merge 1 commit into
dmihalcik-virtru wants to merge 1 commit into
Conversation
Every invocation's timeout is clipped to the cell's deadline. At CI defaults that is nearly all of them: 1500 s across seven cells per SDK gives each about 214 s, against a 600 s timeout_s. So a build that never finishes times out at the deadline, and one_round reclassified any MeasurementError that ended at or after the deadline as BudgetExhausted. That covered a timeout, a crash that happened to land there, and even a full 600 s timeout that overran it. test_benchmarks.py records BudgetExhausted as a skip, and skips fail the gate only when every cell skips. A candidate that hung on every call was therefore reported as "budget ran out during warm-up after 0 of 5 rounds", the other cells passed, and the run was green. An intermittent hang after min_rounds ended the loop as stopped_because "budget", which the step summary does not show. The measured loop also dropped the exception, so even the "only N rounds" skip did not say why. measure() now raises MeasurementTimeout, a MeasurementError subclass, when the launcher reports a timeout, and only that can become BudgetExhausted. It does so when the deadline set the timeout and the cell has no evidence the invocation should have finished: either nothing has completed yet, or it was given less than ten times the longest invocation the cell has completed, any arm, warm-up included. Any other timeout fails the cell, naming the arm, the time it had and that longest invocation. Ten is generous on purpose. The measured loop starts a round only if its median length fits, so an arm the budget really cuts off typically had about a round's time, far short of ten times the cell's slowest run. A cell that earlier cells left with only seconds still skips. The first invocation of a cell has no evidence, so the first warm-up round now runs the reference first, and every candidate's first run can be judged against it. Warm-up samples are discarded and the shuffle still runs in that round, so a seed draws the same measured interleaving as before. If the reference times out before anything has completed, it counts as budget: no candidate has run, and an invocation that cannot finish within the cell's share could not have been measured anyway. With --bench-warmup 0 there is no warm-up round to reorder, and whichever arm is drawn first is judged the same way. When BudgetExhausted propagates, the warm-up and "only N rounds" messages now append the reason one_round gave and chain it as __cause__, so the skip in the report says what happened. Non-zero exits and failures to start are MeasurementErrors whenever they happen, as they already were before the deadline. Genuine budget exhaustion still skips, and the stopping rule and the statistics are unchanged. Signed-off-by: Dave Mihalcik <dmihalcik@virtru.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
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.



Found while reviewing #669. This is a pre-existing bug on
main, so this PR is based onmainand is independent of the stage 2/3 stacks.The bug
Every invocation's timeout is clipped to the cell's deadline. At CI defaults that is nearly every invocation: 1500 s across seven cells per SDK gives each cell about 214 s, against a 600 s
timeout_s.one_roundreclassified anyMeasurementErrorthat ended at or after the deadline asBudgetExhausted. That included a timeout, a crash that happened to land there, and even a full 600 s timeout that overran it.test_benchmarks.pyrecordsBudgetExhaustedas a skip, and skips fail the gate only when every cell skips (nothing_measured).budget ran out during warm-up after 0 of 5 rounds. The other cells passed, and the run was green.min_roundsended the loop asstopped_because: "budget", which the step summary does not show.What it does
Timeouts get their own type.
measure()raisesMeasurementTimeout(MeasurementError)for a timeout, and only that can becomeBudgetExhausted. A non-zero exit or a failure to start is aMeasurementErrorwhenever it happens.When a timeout counts as budget. Both of these must hold:
timeout_s;_HANG_FACTOR(10) times the longest invocation completed in this cell (any arm, warm-up included).Any other timeout fails the cell, in any round, naming the arm, the time it had and that longest invocation.
The reference runs first in the cell's first warm-up round, so a candidate's first run always has evidence to be judged against. Warm-up samples are dropped, and the shuffle still runs in that round, so a seed draws the same measured interleaving as before.
If the reference times out before anything has completed, it counts as budget. No candidate has run yet. A reference that hangs everywhere still fails the run as NOTHING MEASURED.
Skip messages keep their cause. The warm-up and "only N rounds"
BudgetExhaustedmessages append the reasonone_roundgave and chain it as__cause__.README: a new design section, "A timeout fails the cell unless the budget caused it", a "failed cell" note in section 1, and invariant 11.
Behaviour changes
Open questions for review
not longest_s), not as an explicit flag, so thatone_round's signature stays the same and the change does not collide with chore(xtest): measure benchmark cells over a tuple of arms #669.--bench-warmup 0has no warm-up round to reorder. Whichever arm is drawn first is judged with no evidence. This is documented.Validation
uv run pytest test_bench_*.py: 238 passed. ruff, ruff format and pyright are clean.TestTimeoutshas 10 new tests. All 10 fail againstmain'srunner.py. Each uses CI-like numbers (214 s window, 600 s timeout) and covers:min_rounds;test_bench_measure.pyasserts that a timeout is aMeasurementTimeout, and that a non-zero exit and a failure to start are not.Interaction with #669
runner.pyconflicts in four places inone_round's invocation block. Keep this PR's structure, use chore(xtest): measure benchmark cells over a tuple of arms #669'swho(f"{arm.name} ({arm.label})") in the messages, and keep the innerBudgetExhaustedmessages without thecell_idprefix.test_bench_runner.pyconflicts on one import line.TestTimeouts'run_cellcalls take a list of arms, and the expected message text changes towho.