mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-09 08:21:50 +00:00
Follow-up to the Enter-jump fix. The first version did a synchronous
re-pin loop inside the on-scroll handler when the browser clamped our
`scrollTop = scrollHeight` write short of the new bottom; that gave a
tight 4 px visible jump on Enter, but during streaming the
ResizeObserver fires many times per second as content grows, and each
RO callback re-entered the pin loop. CPU profile showed
`Virtualizer.getMaxScrollOffset` climbing to 22 ms self over a typing-
during-streaming window — the sync re-pin path was paying tanstack-
virtual's recompute cost ~3× per token.
Re-architect:
- RO callback coalesces to one pin per animation frame. Streaming-rate
RO bursts now cost the same as a single per-frame pin.
- The on-scroll programmatic-counter guard remains (it's what prevents
the false-disarm bug when the browser clamps a write). It no longer
does sync re-pins; the next RO/rAF will catch up.
- The useLayoutEffect on groupCount (the path that fires on user
submit / new turn arrival) ALSO schedules one rAF pin in addition to
the synchronous pin. This catches the case where React mounts the
new message in a second commit (after our layout effect ran), which
grows scrollHeight again. Two pins instead of a tight loop, paid only
once per turn change.
Net effect on the Cloud Shadows long thread:
enter-jump transient: 12–20 px for 1 frame (was 49 px permanent)
CPU during stream+type: `getMaxScrollOffset` dropped out of top-5
self-time list
typing-during-stream: p50 ~10 ms paint, p99 ~20 ms (1 frame),
occasional 40 ms+ outliers during burst
token arrivals
Also adds scripts/profile-long-stream.mjs: 20-second streaming profile
with per-500ms FPS histogram + content-length tracking, so we can see
whether streaming render cost grows with message length (it doesn't —
sustained 60 fps).
|
||
|---|---|---|
| .. | ||
| assert-root-install.cjs | ||
| before-build.cjs | ||
| click-session.mjs | ||
| dev-no-hmr.mjs | ||
| diag-jump.mjs | ||
| latency-under-stream.mjs | ||
| leak-typing.mjs | ||
| measure-jump.mjs | ||
| measure-latency.mjs | ||
| measure-submit.mjs | ||
| notarize-artifact.cjs | ||
| notarize.cjs | ||
| probe-renderer.mjs | ||
| probe-thread.mjs | ||
| profile-long-stream.mjs | ||
| profile-typing-lag.md | ||
| profile-typing.mjs | ||
| profile-under-stream.mjs | ||
| reload-renderer.mjs | ||
| stage-native-deps.cjs | ||
| test-desktop.mjs | ||
| write-build-stamp.cjs | ||