bench-terminal-resize: pane check samples each window's frames; unsampled or lagging terminals fail
Stacked on #36109: until it merges, this diff also shows its commit (135c1834597). The follow-up is the four commits after it. Review of #36109 (comment 6650044486) plus frame-owner-s4's later rules.
Summary
- Sampler on the window's frames. The pane check sampled on the screen's display link (
FrameScheduler.app). Each window that shows a followed terminal now has aFrameClientonFrameScheduler.forWindow(window), the clock its springs and frame presenter tick on. An observer after Core Animation's commit (beforeWaiting, orderCFIndex.max) samples only the windows whose frame ticked in that turn. A sample is the geometry that turn's commit carried for that window's frame. The doc comment says exactly this. - An unsampled terminal fails. A terminal shown at the round's start with 0 sampled frames fails the round (" was not sampled"). It used to pass on the other terminals' frames.
- A lagging frame fails. frame-owner-s4 set this rule under the m14 contract: a late frame is a failure. A frame whose layer shows another size than its pane after that frame's commit fails the round. The message names the terminal, its lagging frames and the first sizes.
lagging_framesstays in the report. - The docstring is fixed. It named
DebugTerminalPaneFollow, which does not exist; it now namesTerminalPaneFollowProbe. - New data to explain lag. Each terminal adds
in_flight: frames where a size was asked of Ghostty and was not shown yet. The stop reply addsfollow_presenter: the frame presenters' passes, presented, keeps, group waits and fallbacks in the run. The bench carries both into each round, and the arm summaries addin_flight_framesandpresenter_keeps.
Bench only. This PR adds no CI job, step, gate or budget. The probe stays in CmuxNextTerminal, owned by PL-ghostty (session cmux-b6).
Observed / Not run
-
Red, then green:
python3 scripts/cmux-next/tests/test_bench_terminal_resize.py:test_a_terminal_not_sampled_in_the_motion_failsfails at 31c3daf3002 and passes at 6a875677514.test_a_lagging_frame_fails_and_names_the_terminal_its_frames_and_sizesfails at 0c16e59e93c and passes at ed6ba2075bb.- All 27 tests pass at the head.
-
Fleet step
ad3ccfc1219e74f7aeb7b804at 6a875677514 compiled CmuxNext, and the 4TerminalPaneFollowTallyTestspassed, including the new in-flight test. -
A/B
--ab=motion.frameOwner.terminals, keys and keys-stress, 2 rounds per arm, at 6a875677514 (same Swift as the head) on cmux23-perf: stepd557f84ae28f821bd9f55bc1. Held and lagging frames are summed over the round's terminals:layout arm round frames held lagging in flight presenter (passes / presented / keeps) Ghostty host presents (fresh / late) keys off 176, 183 144, 140 144, 140 0, 0 0 / 0 / 0 - keys on 182, 173 0, 0 0, 0 0, 0 28 / 112 / 0 per round 112 / 0 per round keys-stress off 147, 156 168, 182 168, 182 0, 0 0 / 0 / 0 - keys-stress on 150, 140 0, 0 0, 0 0, 0 20 / 140 / 0 per round 140 / 0 per round In this bench build, the ON key rounds still show 0 lagging frames. frame-owner-s4 expected lagging in most spring frames, from pixel-perfect's trace ("presenter request, host frame pending"). I checked whether the 0 comes from sampling at the wrong time. Two counters that do not depend on when the sampler reads say it does not:
- The window's frame presenter kept no frame:
keeps0,fallbacks0, and all 112 (keys) or 140 (keys-stress) requests per round were presented in their own pass. - Ghostty counted 112 or 140 fresh host presents and 0 late presents per round.
The sampler also never saw a size in flight after a commit (
in_flight0). So in the optimized bench build (--config=bench) on cmux23, each key-spring frame's new size was drawn and presented in the commit of the same turn. I did not reproduce pixel-perfect's one-tick lag. The likely cause is a different build or display. A known gap: if the host view itself lags its pane, this check cannot see it, because "pane" here means the host's bounds. - The window's frame presenter kept no frame:
-
With this head's rules, the ON key rounds above pass and the OFF rounds fail (held and lagging). A run with lagging > 0 would now fail. That path is covered only by the unit test, not by a bench run.
-
I moved the run off two minis. cmux17-perf showed idle but did not claim step
4fb4e24064b35b4ba1a0e766for 35 minutes. cmux22-perf was held for a capture pool. I cancelled both steps. -
Not run: drag layouts on this head, and films.
Changelog
none
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
The pane check for bench-terminal-resize now samples each window's own frame clock, so a terminal that is never sampled, or that shows a size other than its pane's, fails the round.
- Each window that shows a followed terminal gets a frame client on its own clock; sampling reads the geometry that turn's commit carried.
- A terminal shown at the round's start with 0 sampled frames fails the round; it used to pass on the other terminals' frames.
- A frame whose layer shows another size than its pane's after that frame's commit fails; the message names the terminal, its lagging frames, and first sizes.
- The stop reply adds per-terminal in-flight frames and frame-presenter counts; arm summaries add in-flight frames and presenter keeps.
- A held drag (
holds_terminals) is data only and no longer excuses a round.
Bench only: no CI job, step, gate, or budget changes.