hermes-agent/apps/desktop/scripts
Brooklyn Nicholson e529694919 perf(desktop): rate-limit thread auto-pin during streaming
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).
2026-05-21 18:02:26 -05:00
..
assert-root-install.cjs Improve desktop runtime UX by surfacing inference readiness in gateway status and hardening WSL link opening. 2026-05-15 16:33:04 -05:00
before-build.cjs feat(desktop): thin installer + first-launch install.ps1 bootstrap 2026-05-18 02:26:46 -04:00
click-session.mjs perf(desktop): cut per-keystroke layout + listener churn in chat composer 2026-05-21 15:45:01 -05:00
dev-no-hmr.mjs perf(desktop): cut per-keystroke layout + listener churn in chat composer 2026-05-21 15:45:01 -05:00
diag-jump.mjs perf(desktop): fix "Enter jumps up" on long threads 2026-05-21 17:45:55 -05:00
latency-under-stream.mjs perf(desktop): cut FadeText forced layouts during streaming 2026-05-21 16:09:44 -05:00
leak-typing.mjs perf(desktop): cut per-keystroke layout + listener churn in chat composer 2026-05-21 15:45:01 -05:00
measure-jump.mjs perf(desktop): fix "Enter jumps up" on long threads 2026-05-21 17:45:55 -05:00
measure-latency.mjs perf(desktop): cut per-keystroke layout + listener churn in chat composer 2026-05-21 15:45:01 -05:00
measure-submit.mjs perf(desktop): cut FadeText forced layouts during streaming 2026-05-21 16:09:44 -05:00
notarize-artifact.cjs fix(desktop): address CodeQL alerts on PR #20059 2026-05-11 16:52:32 -04:00
notarize.cjs ci(desktop): automate desktop releases 2026-05-05 13:04:33 -05:00
probe-renderer.mjs perf(desktop): cut per-keystroke layout + listener churn in chat composer 2026-05-21 15:45:01 -05:00
probe-thread.mjs perf(desktop): fix "Enter jumps up" on long threads 2026-05-21 17:45:55 -05:00
profile-long-stream.mjs perf(desktop): rate-limit thread auto-pin during streaming 2026-05-21 18:02:26 -05:00
profile-typing-lag.md docs(desktop): correct leak-typing numbers on a real session 2026-05-21 17:14:21 -05:00
profile-typing.mjs perf(desktop): cut per-keystroke layout + listener churn in chat composer 2026-05-21 15:45:01 -05:00
profile-under-stream.mjs perf(desktop): cut FadeText forced layouts during streaming 2026-05-21 16:09:44 -05:00
reload-renderer.mjs perf(desktop): cut per-keystroke layout + listener churn in chat composer 2026-05-21 15:45:01 -05:00
stage-native-deps.cjs desktop: swap node-pty fork for upstream microsoft/node-pty 1.1.0 2026-05-18 21:50:53 -07:00
test-desktop.mjs desktop: swap node-pty fork for upstream microsoft/node-pty 1.1.0 2026-05-18 21:50:53 -07:00
write-build-stamp.cjs feat(desktop): thin installer + first-launch install.ps1 bootstrap 2026-05-18 02:26:46 -04:00