Repository navigation
perf: stop repeating render work, overlap thread-open reads and keep recent names - #3570
Draft
kalvinnchau wants to merge 7 commits into
Draft
kalvinnchau wants to merge 7 commits into
kalvinnchau wants to merge 7 commits into
Conversation
every display-name resolve rebuilds the local agent snapshot, which read each agent's execution binding: key validation, storage lookup, json parse, validation and freeze per agent per label. keep the last parsed binding with its storage text and reuse it while the text is unchanged. in a large channel this cut members-dialog keystroke handling roughly in half and search-palette input handling by about 40% in a dev build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kalvin Chau <kalvin@block.xyz>
remote dm voice scans every channel on each agent, channel or choice change, and each eligibility check searched the channel list again for the same channel, making every scan quadratic in channel count. pass the channel the scan already holds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kalvin Chau <kalvin@block.xyz>
activity and reaction rows flattened their preview markdown on every render, and every filter change or live event renders all rows again, remounting rows a filter hid. keep recent previews by text in a bounded least-recently-used cache whose budget counts the source text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kalvin Chau <kalvin@block.xyz>
opening a thread ran four relay reads one after another: the target, its overlays, the root and the first reply window. the overlay read now starts with the target read, and the first strict window read with the root read. rows of each overlapped read are still staged only after the read it used to wait for is validated, and the read is aborted when the outcome is reached without its rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kalvin Chau <kalvin@block.xyz>
leaving a channel gave its roster room back at the end of the task, so switching from a large channel to a small one evicted the least recently used profiles, often the authors of the channel the reader returns to. the timeline then remounted with unresolved names, its saved row measurements no longer matched, and the profiles were read again. a released reservation now holds the cache limit at its own room for 30 seconds; closing a smaller view does not extend the hold. background reads the departing view asked for are still cancelled after the task. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kalvin Chau <kalvin@block.xyz>
… match a timeline mount built its full geometry signature (row content plus resolved author and mention names) before checking for a saved entry. on a first visit, after a community switch, or for a channel pushed out of the three-entry cache there is nothing to compare, so the work was wasted. get now takes the signature lazily and checks the entry and width first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kalvin Chau <kalvin@block.xyz>
the channel sidebar activity callbacks depended on the whole navigation handoff, which is a new object on every navigation state change (a dm being prepared, a lifecycle action starting or ending). each change gave every memoized sidebar row new callback props and rerendered the list. they now depend only on the two stable refs they write. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kalvin Chau <kalvin@block.xyz>
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.
Summary
Seven fixes: four for work the desktop client repeats on every render or every relay update, one for thread-open latency, and two for channel switching. Each one was found in Web Inspector timeline traces of a dev build running against a large community.
features/agents/execution.ts).JSON.parse, validation and freeze, per agent, per label.readnow keeps each validated agent's last parsed binding with its storage text, and reuses it while the text is unchanged.bundled/inbox/InboxRow.tsx).InboxRowButtonandReactionRowButtonranmessagePreview(Markdown → plain text) on every render.useMemowould not help.ByteLru(500 entries, 1 MiB by source length).features/huddle/dm-agent.ts,remote-dm-voice.ts).features/relay/threads.ts).features/relay/profile-directory.ts).features/messages/geometry.ts).getnow takes the signature lazily and checks the saved entry and width first. Hits behave as before.features/channel-navigation/ChannelInventory.tsx).Behavioral changes
What users see is unchanged: the same rows, names, previews and thread contents, in the same order. What changes underneath:
Measurements
These are local, using a dev build (React dev mode with StrictMode, so absolute numbers are inflated) with Safari Web Inspector timelines on macOS. Before and after traces were captured with the same scripted input.
inputhandler per keystroke, steady stateTests
Each new test fails on the base and passes with its change:
execution.test.ts› "reuses a parsed binding until its saved text changes": on the base, the secondreadreturns a new object.remote-dm-voice.test.ts› "checks each channel once per change instead of searching the list again": with 102 channels, the base callschannels.list206 times for one change; the fix calls it fewer than 10 times.thread-target.test.tsandthread-window.test.ts: tests that assumed the old serial order now also assert that the overlapped read is aborted on early outcomes and that a late answer to it never enters the view.profile-details.test.ts› "keeps a closed channel's roster room for a while, so switching back reads no names again": on the base the limit drops to 1,034 as soon as a smaller channel opens; with the fix it holds 1,524 until 30 s, and a smaller view closing during the hold does not extend it (fails if the guard is removed). "cancels a departing view's background reads after the task while its room is held": fails on the base, which shrinks at once.geometry.test.ts› "builds the signature only when a saved entry could match it": fails on the base, which builds it for a missing entry and a width mismatch.ChannelInventory.test.tsx› "keeps sidebar rows still when only navigation state changes": on the base, preparing a DM rerenders every row.InboxRow.test.tsx› "parses a row preview's Markdown once across renders": the base callsmessagePreview3 times across a re-render and a remount; the fix calls it once.Checks run:
bin/pnpm check: passes.bin/pnpm exec vitest run src/bundled/inbox src/features/huddle src/features/agents/execution.test.ts: 24 files, 477 tests passed.bin/pnpm exec vitest run src/features/relay src/features/messages: 254 files passed (1 skipped), 6873 tests passed.bin/pnpm exec vitest run src/features/relay src/features/conversation: 163 files passed (1 skipped), 3858 tests passed.bin/pnpm exec vitest run src/features/messages: 110 files, 3184 tests passed.bin/pnpm exec vitest run src/features/channel-navigation src/bundled/channels src/app/shell: 104 files, 2050 tests passed.Checklist
read; LRU with a byte budget instead of FIFO). A separate review of the thread-read change found no defects; its naming and structure notes are addressed. A review of the profile hold found that any release restarted the hold, so small views could keep a large room up; fixed, with a test.🤖 Generated with Claude Code