fix(perf): commit transcript rows on motion frames

Merged
TE
3d ago
+159-17

Transcript motion currently writes scrollTop in a frame callback, while the browser's scroll event arrives after that frame paints. This keeps virtualization one frame behind a fast motion and can leave the first viewport partially blank. The change routes the existing motion notification through the transcript's normal scroll handling synchronously before paint, cancels stale queued work, and preserves reader follow intent. Zero-duration jumps remain unchanged and no overscan or native logic changes.

Leo: “i feel like the app is slow on scrolling thru stuff... claude desktop is 120hz or something and ours is wack + it has sometimes not even rendered stuff!?”

Performance

Same-worker source A/B: baseline 5dee1ab988ec69569df92ed636c5b971d43f152a, candidate 9e3e8347a19dfe28cfe1cf6c93e337c9736f7d64, fixed tests and harness. Timing and painted-coverage passes are separate. Two rounds are listed in order.

MetricBeforeAfterDeltaHarness or run link
First-motion painted blank frames10−1red/green test, run 41623659964
First-motion blank time (ms)870−87same run
First-motion max uncovered (px)219.250−219.25same run
Fling painted blank frames, rounds 0/11 / 10 / 0−1 / −1same run, painted-coverage pass
Fling painted blank time (ms)16 / 160 / 0−16 / −16same run
Fling max uncovered (px)190.5 / 190.50 / 0−190.5 / −190.5same run
Fling interval p95 (ms)98 / 9481 / 174−17 / +80same run, 3000-row WebKit timing pass
Fling longest frame (ms)123 / 101112 / 192−11 / +91same run
Fling React p95 (ms)75 / 6060 / 110−15 / +50same run
Fling dropped frames/s, nominal 120 Hz103.745 / 104.493101.030 / 109.671−2.715 / +5.178same run
Long-scroll interval p95 (ms)40 / 5242 / 45+2 / −7same run
Wheel interval p95 (ms)28 / 2726 / 24−2 / −3same run
Long-scroll / wheel painted blank frames0 / 00 / 00 / 0same run, both rounds

The coverage improvement is consistent; timing is mixed and does not demonstrate a speedup or native 120 Hz. The completed ABBA follow-up below reproduces large outliers in both variants. Native presentation remains a separate fleet measurement.

Validation at this head: full web check passes; the baseline fails the named first-motion assertion and the candidate passes it, the real six-viewport wheel test and existing regressions. The source and fixed-harness hashes, restored source and all expected stages are verified in the run receipt. Earlier wrapper failures are superseded and provide no product evidence.

Nonblocking review follow-ups: #33672 covers listener rebinding if the read-only scroller is replaced; #33673 covers the existing motion cancellation latch. Neither is a demonstrated current-flow regression.

First-motion ABBA timing follow-up

Run 41627761171, candidate 9e3e8347a19dfe28cfe1cf6c93e337c9736f7d64, baseline 5dee1ab988ec69569df92ed636c5b971d43f152a. Same worker and fixed 3000-row WebKit harness; order A/B/B/A. Each cell lists rounds 0/1. This pass measures timing only; the zero-blank coverage evidence remains the separate run 41623659964.

PassSourceFling p95 (ms)Fling max (ms)React p95 (ms)row.measure p95 (ms)Long p95 (ms)Wheel p95 (ms)
1baseline124 / 116157 / 12480 / 7820 / 2259 / 5028 / 28
2candidate121 / 133131 / 14883 / 9618 / 3049 / 4928 / 26
3candidate161 / 99165 / 130107 / 7227 / 2048 / 4826 / 27
4baseline112 / 184117 / 18981 / 12322 / 4248 / 6726 / 24

Baseline fling p95 spans 112–184 ms; candidate 99–161 ms. Both variants show large variation, and baseline also produces an outlier larger than the prior candidate 174 ms. The prior sample does not isolate a candidate regression. These results establish no reliable speedup, and they remain far above the 8.3 ms target. No averaging of per-run p95s is presented as an aggregate p95.

Receipt acceptance, fixed-source hashes, four log digests, and source restoration passed. Full web check/regression/coverage validation is reused from 41623659964 at the identical candidate tree. The native comparison is complete; the timing result is mixed and does not establish a uniform speedup.

Native pair: one run per arm on the same fleet worker with --app-cache --config=bench --vdisplay=120 --suite=budgets --only=acp --raw=acp. The native result is structural memory and first-content improvement, with mixed interaction timing; the own-mode next-chat value is a single sample and remains an unresolved follow-up rather than a claimed regression or speedup.

Native metric (mode)BeforeAfterDelta
First chat content (chromium)1085.2 ms871.0 ms-214.2 ms (-19.7%)
First chat content (own)949.8 ms789.5 ms-160.3 ms (-16.9%)
Next chat content median (chromium)125.6 ms76.6 ms-49.0 ms
Next chat content median (own, n=1)35.8 ms109.3 ms+73.5 ms; verify before any claim
Memory per extra chat (chromium)453.1 MB137.2 MB-315.9 MB (-70%)
Memory per extra chat (own)490.7 MB118.1 MB-372.6 MB (-76%)
Two-chat footprint (chromium / own)1535 / 1611 MB1217 / 1201 MB-318 / -410 MB
CEF renderer at two chats (chromium / own)882 / 949 MB558 / 562 MB-324 / -387 MB
Typing to paint p50 / p95 / max (chromium)6.3 / 9.9 / 16.7 ms5.2 / 10.5 / 18.8 msmixed
Typing to paint p50 / max (own)5.7 / 19.1 ms5.2 / 14.9 msbetter
Session composer (chromium / own)53.9 / 36.5 ms40.0 / 47.3 msmixed

Native evidence: base step 1825c9e956d52749d471c17c at 5dee1ab988ec69569df92ed636c5b971d43f152a; candidate step 311f1ae7 at 9e3e8347a19dfe28cfe1cf6c93e337c9736f7d64; both ran once on the same fleet worker with identical arguments.

Gallery failures are tracked under #33516, which already records the same isolated Git-action scene failing across unrelated PRs. Diagnostic run 41629680371 rebuilds the exact original merge and replay base: Git-action shift is 0.02984955 on both; composer worktree-search is 0.004427–0.004447 on both, within baseline. Source, loaded CSS/font hashes and sampled geometry match. Neither scene mounts the changed scroller. The original excess shifts do not reproduce from this patch; gallery is not the reason for this hold. This does not claim the shared gallery flake itself is fixed.

Independent review: Opus 5.5 medium SHIP at 5ecd071757bf3dbb390e85cd9bbfddd151c11cc6; formatting-only test delta is carried to this head verified independently; review receipt.

🤖 Generated with Codex

Agent session: agent session