perf(ui): reduce chat session CPU usage from tool call re-renders#2452
perf(ui): reduce chat session CPU usage from tool call re-renders#2452daryllimyt merged 7 commits intomainfrom
Conversation
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.
|
✅ No security or compliance issues detected. Reviewed everything up to f280d33. Security Overview
Detected Code Changes
|
There was a problem hiding this comment.
💡 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.
There was a problem hiding this comment.
💡 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.
Summary
MessagePartinReact.memowith a custom comparator that checks tool parts bytoolCallId,state,input/outputrefs, anderrorText— prevents completed tool calls from re-rendering on every stream chunkToolPayload,ToolInput,ToolOutputinReact.memo— skips JSON serialization and syntax highlighting when payload ref is unchangedgetIconprops to a module-level constant to avoid per-render object allocationuseMemoto avoid per-render.map().join()Context
The Vercel AI SDK creates a new
messagesarray 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
memo-render-count.test.tsx) verifying memoized components skip re-renders with unchanged props