Skip to content

perf(ui): reduce chat session CPU usage from tool call re-renders#2452

Merged
daryllimyt merged 7 commits intomainfrom
perf/tool-call-rerenders
Apr 2, 2026
Merged

perf(ui): reduce chat session CPU usage from tool call re-renders#2452
daryllimyt merged 7 commits intomainfrom
perf/tool-call-rerenders

Conversation

@daryllimyt
Copy link
Copy Markdown
Contributor

@daryllimyt daryllimyt commented Apr 1, 2026

Summary

  • Wrap MessagePart in React.memo with a custom comparator that checks tool parts by toolCallId, state, input/output refs, and errorText — prevents completed tool calls from re-rendering on every stream chunk
  • Wrap ToolPayload, ToolInput, ToolOutput in React.memo — skips JSON serialization and syntax highlighting when payload ref is unchanged
  • Extract source-url filter to a single variable (was filtered 3x per message render)
  • Hoist getIcon props to a module-level constant to avoid per-render object allocation
  • Extract approval key computation to useMemo to avoid per-render .map().join()

Context

The Vercel AI SDK creates a new messages array ref on every stream chunk, cascading re-renders through the entire chat tree. With many tool calls, each re-render triggers redundant JSON.parse/stringify, Blob URL creation, and syntax highlighting for every completed tool call.

Test plan

  • Render-count regression tests added (memo-render-count.test.tsx) verifying memoized components skip re-renders with unchanged props
  • Open a chat session and trigger multiple tool calls (10+)
  • Verify tool call inputs/outputs render correctly during streaming
  • Verify completed tool calls still display correct state after new tool calls stream in
  • Verify approval flow still works (approve, deny, override)
  • Monitor CPU usage in DevTools — should be significantly lower during streaming with many tool calls

Prevents completed tool calls, text, and reasoning parts from
re-rendering on every Vercel AI SDK stream chunk. The custom
comparator checks primitives by value and tool parts by their
toolCallId, state, input/output refs, and errorText.
Prevents redundant JSON serialization (JSON.parse + JSON.stringify),
Blob URL creation, and syntax highlighting when the payload reference
has not changed between renders.
The parts array was filtered 3 times for source-url type per message
render. Extract to a single variable to avoid redundant array scans.
Avoids creating a new { className } object on every render for tool
icon props in MessagePart and ApprovalRequestPart.
Avoids recomputing .map().join() on every render just to produce the
useEffect dependency. The memoized key only recomputes when the
approvals array reference changes.
@daryllimyt daryllimyt added ui Improvements or additions to UI/UX performance Changes that improve performance labels Apr 1, 2026
@zeropath-ai
Copy link
Copy Markdown

zeropath-ai bot commented Apr 1, 2026

No security or compliance issues detected. Reviewed everything up to f280d33.

Security Overview
Detected Code Changes
Change Type Relevant files
Refactor ► frontend/src/components/ai-elements/tool.tsx
    Memoize ToolPayload component
    Memoize ToolInput component
    Memoize ToolOutput component
Refactor ► frontend/src/components/chat/chat-session-pane.tsx
    Memoize MessagePart component
    Introduce TOOL_ICON_PROPS constant
    Use TOOL_ICON_PROPS for tool icons
Refactor ► frontend/src/hooks/use-chat.ts
    Memoize clearError function
Test ► frontend/tests/memo-render-count.test.tsx
    Add tests for memoized chat components
    Verify MessagePart, ToolInput, and ToolOutput memoization
    Mock necessary components and hooks for testing

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 2 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Copy link
Copy Markdown

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

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: ea254dbc81

ℹ️ 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".

Verifies that MessagePart, ToolInput, and ToolOutput do not re-render
when props are unchanged (via React.memo), and correctly re-render
when tool state transitions or payload references change.
Copy link
Copy Markdown

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

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: 8fb543d96f

ℹ️ 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".

clearError was an inline arrow function recreated on every render of
useVercelChat, which propagated through handleSubmitApprovals into the
onSubmitApprovals prop, defeating the React.memo comparator on
MemoizedMessagePart for every stream chunk.
@daryllimyt daryllimyt merged commit 10371ad into main Apr 2, 2026
11 checks passed
@daryllimyt daryllimyt deleted the perf/tool-call-rerenders branch April 2, 2026 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance Changes that improve performance ui Improvements or additions to UI/UX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant