Skip to content

test(timing): pin global idle-cap shift test to the virtual loop clock - #1608

Merged
FrankD412 merged 2 commits into
mainfrom
fix/ci-flake-idle-cap-spawn-join
Oct 25, 2026
Merged

FrankD412 merged 2 commits into
mainfrom
fix/ci-flake-idle-cap-spawn-join

Conversation

@ajcasagrande

@ajcasagrande ajcasagrande commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Root cause

CI flake analysis (55 failed "Run Integration Tests" + 107 failed "Run Unit Tests" runs, Sep 23 – Oct 23):

  • test_global_idle_cap_shifts_real_delayed_continuation_to_ten_seconds failed 6× (incl. main pushes): the test's ±90µs/±10ms approximations encoded a zero-elapsed assumption between timer arming and cap enforcement that real host preemption breaks — CI signatures were exactly constant − ε with ε = 92µs–16ms. Fixed here by pinning the test to the repo's looptime virtual clock (time_traveler_no_patch_sleep), making the arm→cap→assert path exactly zero elapsed — mechanism-true, no tolerance bump.

Related failures investigated and dispositioned (not in this PR):

Verification

  • Fixed test: 100/100 under single-core contention + 50/50 ambient; full unit file 78 passed
  • Integration loop (Failure-2 test): 30/30 iterations / 90/90 param runs; full integration file 16 passed — local + SLURM receipts
  • ruff clean; independent review gate: APPROVED (2 rounds)

AI-assisted fix (investigation + review swarm), verified on SLURM compute.

Summary by CodeRabbit

  • Tests
    • Improved the reliability of automated checks for delayed continuation behavior, reducing sensitivity to timing variation.

test_global_idle_cap_shifts_real_delayed_continuation_to_ten_seconds failed
intermittently in CI (6 runs, incl. main pushes, Sep 28-Oct 16) with
signatures like 'assert 89.99989932800008 == 90.0 +- 9.0e-05' and
'assert 9.983999999999924 == 10.0 +- 0.01'.

Root cause: the test's expectations are only exact if zero loop time passes
between three internal sample points. The mechanism's actual contract is that
cap_pending_delay retargets the pending continuation timer to
enforcement_time + cap: the skipped amount is delay - (t_cap - t_arm) - cap,
where t_cap - t_arm is the loop-time elapsed between the timer's arming inside
handle_credit_return and the enforcement's loop.time() sample. Any host
preemption in that window (CI observed 100us-16ms) is subtracted from the
asserted constants, breaking approx(90.0) (+-90us) and, for the post-condition
handle.when() - loop.time(), the test's own later clock read drifts by the
same unbounded amount, breaking approx(10.0, abs=0.01). The cap itself fires
exactly on time; the test encoded a zero-elapsed assumption the mechanism
never promised.

Fix: run the test on the virtual loop clock (looptime via the repo's
time_traveler_no_patch_sleep fixture, the established pattern in the two
neighboring idle-cap tests). The arm-to-cap-to-assert path never yields to
the event loop, so the elapsed loop time is exactly zero and both asserted
quantities become deterministic mechanism truths. No sleeps are involved, so
the no-patch-sleep variant is the right fixture.
I, Anthony Casagrande <acasagrande@nvidia.com>, hereby add my Signed-off-by
to commit 10f2e3a
(test(timing): pin global idle-cap shift test to the virtual loop clock).

I certify that the contents of the referenced commit are in accordance with
the Developer Certificate of Origin, per CONTRIBUTING.md.

Signed-off-by: Anthony Casagrande <acasagrande@nvidia.com>
@ajcasagrande
ajcasagrande requested a review from a team as a code owner October 24, 2026 00:08
@github-actions

Copy link
Copy Markdown

Try out this PR

Quick install:

pip install --upgrade --force-reinstall git+https://github.com/ai-dynamo/aiperf.git@04621cec5fc10ff8bdf871053ae573996aa42599

Recommended with virtual environment (using uv):

uv venv --python 3.12 && source .venv/bin/activate
uv pip install --upgrade --force-reinstall git+https://github.com/ai-dynamo/aiperf.git@04621cec5fc10ff8bdf871053ae573996aa42599

Last updated for commit: 04621ce • Browse code

@github-actions github-actions Bot added the test label Oct 24, 2026
@coderabbitai

coderabbitai Bot commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between 1558551 and 04621ce.

📒 Files selected for processing: 1
  • tests/unit/timing/strategies/test_agentic_replay.py

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 7 remain after this review.

Walkthrough

The replay timing test now accepts the time_traveler_no_patch_sleep fixture. Its docstring explains how virtual loop time makes the timer-arm-to-enforcement interval deterministic when the test does not yield.

Changes

Replay timing test

Layer / File(s) Summary
Deterministic timer assertions
tests/unit/timing/strategies/test_agentic_replay.py
The test uses virtual loop time so host preemption does not affect its skipped-delay and remaining-timer assertions.

Priority: ⬇️ Low

Estimated code review effort: 1 (Trivial) | ~3 minutes

Merge Risk: ⚪ Minimal · up to 04621

The test change makes timing assertions deterministic without introducing a merge-blocking risk.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely identifies the timing test change and the use of the virtual loop clock. It matches the main purpose of the pull request.
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

A rabbit checks the timer’s pace
Virtual time keeps steps in place
No yield shifts the waiting span
The test now follows its plan
I nibble carrots, pleased with grace

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Oct 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@ajcasagrande

Copy link
Copy Markdown
Contributor Author

Reviewed all three bot comments. The installation instructions reference the current head, CodeRabbit reports no actionable findings, and Codecov reports coverage of modified coverable lines. Source inspection confirms the test uses time_traveler_no_patch_sleep. No additional changes were needed; no local tests were run.

@FrankD412 FrankD412 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Root cause checks out, and this fixes the mechanism instead of loosening the tolerance.

Verified locally on 04621ce:

  • Full test_agentic_replay.py: 78 passed.

  • Injected a real time.sleep() between handle_credit_return and enforce_system_idle_cap and ran the old (real-clock) and new versions side by side:

    Injected delay Old (real clock) New (looptime)
    0 fail, skipped=89.99988 (ε≈123µs from test overhead alone) pass
    200µs fail, 89.99967 pass
    20ms fail, 89.97983 pass (30/30)

    The old test fails here even with no injected delay, so the ±90µs approx(90.0) was always tight against normal test overhead. Under the fixture, loop.time() and time.monotonic() both advance by exactly 0.0 across a 20ms time.sleep, which matches the docstring's "exactly zero" claim.

  • The other two idle-cap tests that drive a real LoopScheduler (..._watchdog_bounds_persistent_control_plane_work, ..._rechecks_after_barrier_defers_near_timer) already use time_traveler_no_patch_sleep, so this brings the last one into line. No other sibling has the same exposure.

Non-blocking nit: with elapsed time now exactly zero, approx(10.0, abs=0.01) is far looser than needed. Default approx(10.0) (or exact equality) would catch a regression in the retarget arithmetic that a 10ms window could hide. Fine as-is if you'd rather keep the margin.

LGTM.

@FrankD412
FrankD412 merged commit 8b8b5a6 into main Oct 25, 2026
42 checks passed
@FrankD412
FrankD412 deleted the fix/ci-flake-idle-cap-spawn-join branch October 25, 2026 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants