Repository navigation
perf: large threads open from a viewport snapshot, and typing and streaming render less - #18220
Open
maria-rcks wants to merge 118 commits into
Open
maria-rcks wants to merge 118 commits into
maria-rcks wants to merge 118 commits into
Conversation
… failure or added context ArrowUp from an empty window waits for an older page. With no recall position, typing, a send or a failed page left that wait in place, so a later page filled the composer with an old or just-sent prompt. An image, file, terminal context, annotation, review comment, approval or question added while the page loaded was ignored too. Each of these now ends the wait.
…ipped When a concurrent render brought an older prompt than the editor held, the editor kept its text but its latest-value ref still pointed at the older prompt, so selection updates and focusAt waited for a rewrite that never came.
Coverage started at the tenth latest user turn and capped raw turns at 150, two turns short of a turn-aligned window. It now starts at the twelfth latest user turn with the same raw cap, and lists every run when there are fewer.
The 30 s idle TTL on diff previews made a panel reopened after a short idle show loading. Previews are keyed by scope again with the default TTL, and a new cache key refreshes the preview in place, so a superseded preview is never kept beside the current one. The preview request no longer carries the cache key: the server keeps no finished previews, so the key only joined the same atom's own in-flight request.
Mobile caches the viewport snapshot, whose deferred checkpoints have empty file lists. After an OTA rollback an older bundle showed those turns with no changes. Such entries are now wrapped in an envelope that older bundles fail to decode, so they drop the entry and load live, as web does.
Wave 3 added an optional cacheKey to diff preview requests and a server Cache keyed by it. Since previews stopped keeping finished reads and the web panel stopped sending the key, nothing uses it, and older clients never sent it. The contract field, the cache and its tests go back to the plain read.
The test still expected every other version's cache directory to go on start. Since 4514cbc only directories unused for a week go, so it now checks that a stale one goes and a recently used one stays.
LinuxSnapShot imported NiriSnapShot lazily, but the entry chunk already holds it, so the lazy chunk required application.cjs. conf evicts that file from the require cache, so every capture support check or capture re-ran the whole entry and added listeners. Import it statically, and check that no real chunk requires the entry.
The wrapper error's stack omitted its cause, so a packaged crash showed only "Desktop module initialization failed" at main.cjs. Let the original error propagate once the stack limit is restored.
The store reads two rows beyond the 75-row window and returns full checkpoints for every run in them. The bounded snapshot dropped a checkpoint whose run only reached those rows, so the Diff panel and Review skipped that turn until the user paged up. Keep it listed with its files deferred.
A thread with no user turn among its latest 152 turn starts listed deferred checkpoints back to the 152nd turn, and the list jumped between 151 and 152 turns. Base listed only the window's runs; match it.
Web's cache waits for an idle callback after the deleted check. A deletion in that wait removed the entry, and the delayed write then recreated it. Remove the entry again when the thread was deleted by the time the write lands.
…lete The compact envelope was written only when something was compacted or deferred, so a viewport window could be cached plain and an older build would resume from it as the whole thread. Write every thread entry in the envelope, which older builds skip in favor of live data. Plain entries still load.
Field patches only updated a read row that was current, so a row an older build marked stale stayed stale through visits and turns, and shell, search and sweep readers kept decoding the full payload. Rebuild a stale or missing row from the thread once, as these paths did before, and keep the cheap JSON patch for current rows.
juliusmarminge
added this pull request to stack #18313
October 11, 2026 19:04
Rows past the first-paint budget mounted as placeholders, so the motion pass animated the placeholder and the observer swapped in the real row at rest a frame later. Rows that join an already painted list now read their real box before paint, and the list motion moves an in-flight animation onto the element that replaces a slot. A row that leaves fades out as the element that was on screen rather than its stale slot.
A row that changed variant reused its old box by thread key, so a card settling into the Settled shelf slid its slim replacement across the list. Positions now carry over only when the variant matches: the card fades out where it was and the slim row fades in at its slot.
This branch has not been deployed
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.
stacked on #18219, which is stacked on #17609. this diff shows only this layer.
after the first two layers, the largest thread (4,495 items) still loaded a 4.6 MB snapshot and decoded it in one long task. every streamed batch re-rendered the whole chat view. every keystroke re-rendered the composer frame. the desktop composer waited for a boot transition that other startup work kept restarting. this layer removes that work:
the whole stack against main 18656a3:
measurement: built artifacts on one 16-core linux host. web runs in chromium 1223 and chrome-headless-shell 154. desktop is electron 44.4.5 under xvfb (software rendering). the server uses the 75-thread seed and a 1,350-thread copy. all four sides ran interleaved in the same batches, at loadavg 0.9-6.5. the numbers come from 1634ef4. the final-review fixes after it address correctness. on measured paths they grow the viewport snapshot 0.5% (it now covers the last 10 user turns) and drop a boot read in new tabs that saved 6 ms.
what got slower:
compatibility:
deferredFileCountis optional.verification:
known minor gaps, left for follow-ups:
unverified: macos and windows desktop, real gpu compositing, physical IME, native mobile, relay and tunnel at runtime.
model: claude-opus-5-5 coordinating gpt-6.1-sol and claude subagents, harness: claude code in t3 code. latest integration: gpt-6.1-sol through the codex harness in t3 code.