fix(desktop): make render-churn measure streaming, not boot churn - #72212
Merged
Merged
Conversation
Two problems, both found by distrusting the harness's own numbers. 1. The scenario slept a fixed 1s after mounting tabs, then recorded. Boot and session hydration are not reliably done by then, so a variable amount of unrelated work landed inside the measurement window. Three back-to-back runs on identical code spread 2.2x on total_renders and 3.8x on wasted_renders — wide enough that a single-run before/after delta could be mostly noise. Replaced with a quiesce gate that waits for commits to hold still before recording, and reports 'quiet:N' or 'timeout:...' so a contaminated run is visible instead of silent. 2. The counter attributed a context-driven re-render as 'wasted', which pointed at memo() as the fix when memo cannot block context at all. Adds contextChanged via the fiber's context dependency list, and excludes it from wasted. The gate also turned up a finding worth more than the fix: with five busy tiles and NO driver running, the renderer still commits ~18x/sec. The report now names the cascade roots (own state changed, props did not) rather than leaving them to be guessed at — Streamdown re-renders itself 105 times while idle, which is what drives Block/Ct.
Contributor
૮ >ﻌ< ა ci reviewran on f7aee9d all good! |
randlee
pushed a commit
to randlee/hermes-agent
that referenced
this pull request
Aug 11, 2026
…anscript-renders fix(desktop): make render-churn measure streaming, not boot churn
prmartinow
pushed a commit
to prmartinow/hermes-agent
that referenced
this pull request
Aug 26, 2026
…anscript-renders fix(desktop): make render-churn measure streaming, not boot churn
melon-xf
added a commit
to melon-xf/hermes-agent
that referenced
this pull request
Sep 3, 2026
…anscript-renders fix(desktop): make render-churn measure streaming, not boot churn
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Trust-the-instrument work before the next perf fix. Brooklyn pushed on whether the harness was actually valid given the gateway errors scrolling past every spawn — the errors turned out to be harmless, but checking found the harness itself was not trustworthy.
The measurement was mostly noise
Three back-to-back runs, identical code:
2.2x spread on renders, 3.8x on wasted. Wide enough that a single-run before/after delta is as likely to be measuring machine load as a code change.
Cause: the scenario slept a fixed 1s after mounting tabs and then recorded. Session hydration isn't reliably finished by then, so a variable amount of boot work landed inside the window — which is why the bad run's top offenders were
Primitive.divandTooltipProviderrather than anything on the streaming path.Replaced with a quiesce gate: poll the commit counter until it holds still, then record. It reports
quiet:N(comparable) ortimeout:...(contaminated) so a bad run is visible in the output instead of quietly skewing a number.The counter was mis-attributing
wastedcounted any render with no changed props and no changed hook state — which lumped in context-driven renders. That points atmemo()as the fix, andmemo()cannot block a context update at all. AddscontextChangedoff the fiber's context dependency list and excludes it fromwasted.This immediately disproved my own working theory:
Block/Ctcome backprops=0, state=0, ctx=0, so the streamdown context I suspected is not involved.The finding that matters more than the fix
With five busy tiles and no driver running, the renderer still commits ~18x/sec.
Block/Ctrender 800 times while completely idle — more than during the actual streaming window. So the transcript cost I was about to "fix" is substantially an idle-churn problem, not a streaming one.The report now names cascade roots (own state changed, props did not) instead of leaving them to be guessed:
Streamdownre-rendering itself 105 times while idle is what drivesBlock/Ct. That's the next PR — this one just makes it measurable.No behavior change; instrumentation and harness only.