Repository navigation
perf(relay): look up archived identities in a per-snapshot set - #2359
Conversation
archiveHides scanned the frozen archived list with includes for every search and chooser candidate, so each cmd+k render cost candidates x archived identities. build one set per snapshot list in a weakmap. Signed-off-by: Kalvin Chau <kalvin@block.xyz> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: peon <9ac6794b000690b7e814eb1805ad32405d0bec7d52838de3a86cf967565dacc0@buzz.block.builderlab.xyz>
f714bf8 to
2f87dc5
Compare
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord automated source review via Wes’s account.
No actionable findings in the diff from base fae935a363bd682d128ba7962fd237b99062902b to head 2f87dc5d9851e0dee7d7c1cf9426c0b628d3604b.
Reviewed the per-array WeakMap cache, archive snapshot replacement and clearing, retained visibility during loading/errors, viewer exemption, and search/chooser/mention callers. The current producers preserve each array’s contents, and the changed fixture publishes a fresh copy on refresh. This supports reusing a Set for each list without changing membership answers.
Coverage: Rocket (systems/performance/lifecycle), Mantis (correctness/security), Groot (product/callers), and Star Lord (integration and public description/commit inspection). Source-only: no tests, app workflows, browser/native interaction, or benchmarks were run. The PR’s timing and test results were not independently verified.
* origin/main: (26 commits) fix(identity): read FI backup status through the native forwarder (#2344) fix(relay): show the relay's reason when it refuses a write (#2031) perf(relay): look up archived identities in a per-snapshot set (#2359) fix(messages): keep link previews clear of message hover actions (#2351) fix(security): close workflow, Canvas, upload, and broker gaps (#2360) fix: prevent false leave failures after membership updates (#2310) feat(bestie): remove your Bestie, and let remote agents be Bestie after a warning (#2041) feat(messages): open the sender's profile from the byline name (#2253) feat(native-mcp): one-command launcher and MCP registration for agent driving (#2272) perf(composer): stop per-keystroke chip re-renders and reparses in long rich drafts (#2251) fix(agents): prevent history from forging prompt requests (#2223) Enable automatic key backup in preview releases (#2325) feat(read-state): n-blob NIP-RS sync with a 30-day floor, frontier only (#1286) feat(huddles): provide read-only huddleStatus for optional consumers (#2327) feat(search): show verified names in people search (#2322) Fix voice-note sending and restore waveform previews (#2283) Preserve Solo queued messages across restarts (#1704) feat(plugins): resolve attachment renderers by order, like panels and links (#2284) fix(channels): keep muted DM names from becoming bold (#2184) fix: command-click opening desktop message links in the browser (#2288) ... Co-authored-by: Codex <noreply@openai.com> Co-authored-by: Tyler Longwell <tlongwell@squareup.com> Signed-off-by: Tyler Longwell <tlongwell@squareup.com> # Conflicts: # src/bundled/huddles/index.tsx # src/features/huddle/service.test.ts
Problem
A WebKit timeline recording of cmd+k channel navigation with many agents running shows the search palette's
SearchResultsrender taking about 35% of JS samples. About 2,800 of 11,390 samples (~25% of all JS) are inarchiveHides(), which callssnapshot().archived.includes(pubkey)for every person and agent candidate on every render. Each render therefore costs candidates × archived identities, and agent traffic re-renders the open palette repeatedly.Change
archiveHidesbuilds oneSetper archived list, cached in aWeakMapkeyed by that list. The store freezes a new list for each snapshot, so a cached Set always matches its snapshot. One agent-choices test fixture changed its archived list in place; it now publishes a new frozen list on each read, as the store does.No behavior changes
Same answers for every input: the viewer is never hidden, missing archives hide nobody, and every other key is hidden exactly when it is in the snapshot's archived list.
Evidence
Both implementations as they are in the source, interleaved, one call per candidate per render. Median ms per render, 6 runs per cell, on 2 Linux and 2 macOS workstations (macOS also in JavaScriptCore, the desktop engine).
Lower is better. Each value is JS time for one palette render's archive checks.
macOS node (V8) gives the same shape: 62.38 → 0.07 ms (−99.9%) at 5,000 × 3,000.
Checks:
tscand biome are clean. The identity-archives, SearchResults, agent choices, mention admission, session agent admission, ChannelMembersDialog and solo suites pass (494 tests). There is no new test, because only speed changes.🤖 Generated with Claude Code