Skip to content

perf: Tier 1 dashboard rendering optimizations - #88

Merged
aterrylu merged 1 commit into
mainfrom
terry/perf-tier1
Mar 27, 2026
Merged

perf: Tier 1 dashboard rendering optimizations#88
aterrylu merged 1 commit into
mainfrom
terry/perf-tier1

Conversation

@aterrylu

Copy link
Copy Markdown
Owner

Summary

  • CSS spinner replaces setInterval(100ms) + React state → zero JS re-renders during animation
  • Polling equality guards on fetchSessions and fetchNotifications skip set() when data unchanged, preventing subscriber re-renders on every 3s/5s poll
  • useShallow consolidates 18 separate Zustand subscriptions in Sidebar into 2 focused selectors (data + actions)
  • rAF debounce batches notifySlotUpdate from ResizeObserver, coalescing multiple callbacks per frame
  • React.memo on GroupContainer prevents unnecessary re-renders from parent state changes

Problem

Dashboard was sluggish when clicking UI elements — React DevTools profiler showed 70+ unnecessary re-renders/sec from:

  1. N agents × 10fps JS spinner state updates
  2. Polling always writing new objects to store (even when data unchanged)
  3. 18 separate Zustand subscriptions in Sidebar (every store change triggers 18 equality checks)
  4. Unbatched ResizeObserver notifications causing re-render storms in SessionMountLayer

Changes

Fix File Impact
CSS @keyframes spinner agent-status-icon.tsx Eliminates N×10fps React renders
fetchNotifications equality guard store.ts Skips ~95% of 3s poll writes
useShallow selector split Sidebar.tsx 18 subscriptions → 2, data vs actions
fetchSessions equality guard store.ts Skips ~95% of 5s poll writes
rAF debounce notifySlotUpdate SessionMountLayer.tsx Batches resize callbacks per frame
React.memo GroupContainer Sidebar.tsx Prevents parent-triggered re-renders

Test plan

  • Build passes (npm run build)
  • Biome lint clean
  • /polish — code-reviewer, code-simplifier, silent-failure-hunter all run
  • Manual testing: UI feels noticeably snappier, spinners animate correctly
  • Verify agent status transitions still update (working → idle → needs_input)
  • Verify session list updates when sessions are created/destroyed
  • Verify notification badges update on new messages

🤖 Generated with Claude Code

@aterrylu
aterrylu enabled auto-merge (squash) March 27, 2026 17:44
Eliminate 70+ unnecessary React re-renders/sec from JS spinners, polling
writes, subscription fan-out, and unbatched ResizeObserver notifications.

Six fixes:
1. CSS @Keyframes spinner replaces setInterval(100ms) state updates
2. fetchNotifications equality guard skips set() when data unchanged
3. useShallow splits Sidebar into data selectors + stable action refs
4. fetchSessions equality guard compares id/name/status/claudeSessionId
5. rAF debounce batches notifySlotUpdate per frame
6. React.memo on GroupContainer prevents parent-triggered re-renders

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant