mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-15 04:12:25 +00:00
perf(tui): instrument scroll fast-path decline reasons
Adds scrollFastPathStats counters to render-node-to-output.ts: captures every time a ScrollBox's DECSTBM scroll hint is generated, records whether the fast path took it (blit+shift from prevScreen) or declined, and why. Exposed through hermes-ink's public exports and snapshotted on every FrameEvent so the profiler harness can correlate decline reasons with the actual patch/renderer cost per frame. This is pure observation — no behaviour change. Preparing for the virtual-history rewrite: the hypothesis was that our topSpacer/ bottomSpacer scheme disqualifies every scroll via heightDelta mismatch, but the data shows the fast path is actually taken on most scrolls (19/23 over a 6s PageUp hold through 1100 messages) — the remaining steady-state renderer cost is Yoga tree traversal, not the per-frame full redraw I initially suspected. Declines that do happen correlate with React commits that changed the mounted range mid-scroll (heightDelta=±3 to ±35). Those are the rarer cases the virtualization rewrite still needs to address. No test diffs — instrumentation-only. Build verified: `tsc --noEmit` plus the full `npm run build` compiler post-pass pass cleanly.
This commit is contained in:
parent
71eee26640
commit
cd7a200e6c
4 changed files with 114 additions and 0 deletions
|
|
@ -44,6 +44,7 @@ import { homedir } from 'node:os'
|
|||
import { dirname, join } from 'node:path'
|
||||
|
||||
import type { FrameEvent } from '@hermes/ink'
|
||||
import { scrollFastPathStats } from '@hermes/ink'
|
||||
import { Profiler, type ProfilerOnRenderCallback, type ReactNode } from 'react'
|
||||
|
||||
const ENABLED = /^(?:1|true|yes|on)$/i.test((process.env.HERMES_DEV_PERF ?? '').trim())
|
||||
|
|
@ -122,8 +123,29 @@ export const logFrameEvent = ENABLED
|
|||
return
|
||||
}
|
||||
|
||||
// Snapshot the fast-path counters each frame. Cumulative values —
|
||||
// consumers diff pairs to get per-frame deltas. Written verbatim
|
||||
// so we can also see "last*" fields (which decline reason fired,
|
||||
// and what the height math looked like).
|
||||
const fastPath = {
|
||||
captured: scrollFastPathStats.captured,
|
||||
taken: scrollFastPathStats.taken,
|
||||
declined: {
|
||||
heightDeltaMismatch: scrollFastPathStats.declined.heightDeltaMismatch,
|
||||
noHint: scrollFastPathStats.declined.noHint,
|
||||
noPrevScreen: scrollFastPathStats.declined.noPrevScreen,
|
||||
other: scrollFastPathStats.declined.other
|
||||
},
|
||||
lastDeclineReason: scrollFastPathStats.lastDeclineReason,
|
||||
lastHeightDelta: scrollFastPathStats.lastHeightDelta,
|
||||
lastHintDelta: scrollFastPathStats.lastHintDelta,
|
||||
lastPrevHeight: scrollFastPathStats.lastPrevHeight,
|
||||
lastScrollHeight: scrollFastPathStats.lastScrollHeight
|
||||
}
|
||||
|
||||
writeRow({
|
||||
durationMs: round2(event.durationMs),
|
||||
fastPath,
|
||||
flickers: event.flickers.length ? event.flickers : undefined,
|
||||
phases: event.phases
|
||||
? {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue