Skip to content

perf(messages): index the emoji catalog for reaction lookups - #333

Merged
wesbillman merged 1 commit into
mainfrom
murderbot/reaction-controls-lookup
Sep 28, 2026
Merged

wesbillman merged 1 commit into
mainfrom
murderbot/reaction-controls-lookup

Conversation

@baxen

@baxen baxen commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator

What

Every message row renders the hover quick-reaction buttons (👍 ❤️ 😂). To decide whether each is a custom emoji, MessageReactionControls ran catalog.entries.find(e => :${e.shortcode}: === content.toLowerCase()) over the whole custom-emoji catalog — three full scans per row, on every render, allocating a string per entry. Native emoji never match, so every scan was a worst case.

This change:

  • builds a shortcode → entry Map once per catalog snapshot (cached in a WeakMap keyed on the frozen snapshot from emoji-directory.ts)
  • returns early for any content that doesn't start with :, so native emoji never touch the catalog
  • reuses the same helper for the two click-time lookups

Single file: src/features/messages/MessageReactions.tsx. Rendered output is unchanged.

Evidence

Headless Chromium via Playwright against just web (Vite dev build), cold start → open 4 channels → scroll history, DevTools trace with CPU samples, then attributed every sample inside 50 ms+ main-thread tasks. Two runs each, back to back, same account.

before after
Total time in 50 ms+ tasks 3.97 s / 3.70 s 2.68 s / 2.39 s
Time over the 50 ms line 1.87 s / 1.75 s 1.03 s / 0.99 s
Long tasks 42 / 39 33 / 28
MessageReactionControls self+children ~590 ms ~30 ms

About half of what remains is React dev-only runtime (jsxDEV, dev react-dom), absent in release. The scan removed here is app code, so the ~0.5 s saving should carry over to release builds. The workload was a light account (4 channels); cost scales with rendered rows × catalog size.

Checks

  • tsc and biome clean
  • src/features/messages vitest: 47 files, 682 tests pass

🤖 Generated with Claude Code

Every message row resolved its quick reactions by scanning the whole custom
emoji catalog, building a string per entry, on every render. Index each
catalog snapshot once and skip the lookup for native emoji.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: murderbot <3754f8729004d95654c46dbab3129e4ab9ef05cc2534e2a3fbfc155983bd637b@buzz.block.builderlab.xyz>
@baxen
baxen marked this pull request as ready for review September 28, 2026 02:49
@baxen
baxen requested review from a team, comp615 and wesbillman as code owners September 28, 2026 02:49
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-28T02:52:33.151275Z 3c2ef35 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3c2ef35e9c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

);
}

const catalogIndexes = new WeakMap<

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the required Signed-off-by trailer

The target commit contains no Signed-off-by trailer. Any PR containing this commit will therefore violate the repository's per-commit DCO requirement and fail the hosted DCO Check; recreate the commit with the actual author's verified name/email and sign-off.

AGENTS.md reference: AGENTS.md:L151-L161

Useful? React with 👍 / 👎.

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Star Lord — automated source review via Wes's account

No actionable findings. The change meets the 9/10 source-review bar for minimalness, elegance, and correctness within this focused optimization.

Reviewed head 3c2ef35e9cecb03d826152dcc16ce331982fe710 against base/merge-base 85d6bf82c54d1c8d930d58444597a1fe31cc8975 using pinned, blob-hash-verified source; no dirty working-tree inputs.

The lookup replacement preserves the supported catalog contract:

  • emoji.ts:10–28 normalizes shortcodes and freezes entries; emoji-directory.ts:72–89 deduplicates winners and publishes a fresh frozen array. Consequently, indexing by array identity does not reuse stale entries after catalog replacement, and Map lookup does not change duplicate-selection behavior.
  • Each session owns its directory (session.ts:563,1557); clear/dispose replace the entries array. The module-level WeakMap shares work across rows without keying different communities by shortcode alone.
  • Native reactions bypass the catalog, case-insensitive custom lookup is retained, and historical pills still toggle their event-local emoji URL (MessageReactions.tsx:310), not the current catalog URL.

Read the repository instructions, contribution/channel contracts, and Buzz vision documents. Existing test source covers native toggles, current-vs-historical custom URLs, normalization, replacement, and session isolation. This PR adds no tests; I did not execute any tests, PR code, or application workflow, and did not reproduce the reported performance measurements.

One exact-head CI snapshot at 2026-09-28 02:53:53 UTC showed JavaScript, browser measurements, DCO, Semgrep, and zizmor successful; browser journeys and Rust/tool integration were still running, and Windows validation was skipped. CI completion, runtime behavior, and release-build performance remain unverified. This is a non-blocking COMMENT review, not approval or merge authorization.

@wesbillman
wesbillman merged commit a1b767c into main Sep 28, 2026
14 checks passed
@wesbillman
wesbillman deleted the murderbot/reaction-controls-lookup branch September 28, 2026 16:30
johnmatthewtennant pushed a commit that referenced this pull request Sep 28, 2026
* origin/main: (45 commits)
  Use Blue 11 links with Blue 3 hover and explicit contrast exceptions (#322)
  perf(messages): index the emoji catalog for reaction lookups (#333)
  Polish search palette and add conversation search (#340)
  Use step-ten avatar colors with contrasting outlines (#320)
  Keep profile avatar cutouts transparent and align the header gutter (#319)
  Restore sidebar status icons beside names (#316)
  docs(mentions): specify portable mention rules (#343)
  fix(agents): wait for native host operations (#331)
  Simplify channel templates and report setup failures accurately (#318)
  feat(agents): Harnesses Goose install (slice 3/5) (#279)
  feat(agents): Harnesses status card in Settings (slice 2/5, stacked on #272) (#277)
  Fix timer operation ownership and stabilize timing regressions (#317)
  Restore cached workspace before relay startup (#311)
  test(browser): wait for the app's own quota cooldown before retrying (#284)
  docs: define Harnesses setup and global agent defaults (#272)
  Make mention choices consistent and stable (#258)
  Discover saved relay agents without changing the page (#224)
  feat: add persistent dev log levels and relay traffic summaries (#306)
  Polish inline message reactions and previews (#213)
  feat(identity): add native macOS import, creation and backup (#308)
  ...

Signed-off-by: Sol <49aa1f65411fd096d2e2ec144f1e7aa36fdc76d1b907cfdf7be000c66f9d3b8e@buzz.block.builderlab.xyz>

# Conflicts:
#	src/bundled/agents/AgentCard.tsx
#	src/bundled/agents/AgentsPage.tsx
johnmatthewtennant pushed a commit that referenced this pull request Sep 28, 2026
* origin/main: (36 commits)
  Delay message timestamp tooltips by 500 ms (#321)
  Use Blue 11 links with Blue 3 hover and explicit contrast exceptions (#322)
  perf(messages): index the emoji catalog for reaction lookups (#333)
  Polish search palette and add conversation search (#340)
  Use step-ten avatar colors with contrasting outlines (#320)
  Keep profile avatar cutouts transparent and align the header gutter (#319)
  Restore sidebar status icons beside names (#316)
  docs(mentions): specify portable mention rules (#343)
  fix(agents): wait for native host operations (#331)
  Simplify channel templates and report setup failures accurately (#318)
  feat(agents): Harnesses Goose install (slice 3/5) (#279)
  feat(agents): Harnesses status card in Settings (slice 2/5, stacked on #272) (#277)
  Fix timer operation ownership and stabilize timing regressions (#317)
  Restore cached workspace before relay startup (#311)
  test(browser): wait for the app's own quota cooldown before retrying (#284)
  docs: define Harnesses setup and global agent defaults (#272)
  Make mention choices consistent and stable (#258)
  Discover saved relay agents without changing the page (#224)
  feat: add persistent dev log levels and relay traffic summaries (#306)
  Polish inline message reactions and previews (#213)
  ...

Signed-off-by: Sol <49aa1f65411fd096d2e2ec144f1e7aa36fdc76d1b907cfdf7be000c66f9d3b8e@buzz.block.builderlab.xyz>

# Conflicts:
#	src/bundled/agents/AgentEditor.tsx
#	src/bundled/profiles/ProfileAgentIdentity.test.tsx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants