Skip to content

perf: skip syntax highlighting while a message is streaming - #433

Open
k0n9-devx wants to merge 1 commit into
agegr:mainfrom
k0n9-devx:perf/streaming-render
Open

perf: skip syntax highlighting while a message is streaming#433
k0n9-devx wants to merge 1 commit into
agegr:mainfrom
k0n9-devx:perf/streaming-render

Conversation

@k0n9-devx

@k0n9-devx k0n9-devx commented Aug 8, 2026

Copy link
Copy Markdown

Problem

While a message streams, every message_update re-renders the live MessageView, and CodeBlock re-runs Prism over the entire growing code fence on each update. A long code block gets re-tokenized hundreds of times before it completes. On phones this is the largest single CPU cost of streamed rendering — enough to cause visible thermal throttling on remote access.

Two smaller issues compound it:

  • CodeBlock isn't memoized, so any parent markdown re-render re-tokenizes unchanged code.
  • ChatWindow rebuilds the toolResults map inline on every render, giving it a new identity each time.

Change

  • Code fences render as plain monospace text (same block chrome) while the owning message is streaming; Prism runs once when the message completes. The mermaid source view follows the same rule.
  • Wrap CodeBlock in memo.
  • Hoist the toolResults map into a useMemo keyed on messages so its identity is stable across streaming updates.

Testing

  • tsc --noEmit and eslint clean
  • Component tests and lib/markdown.test.mjs pass; added two CodeBlock tests (plain output while streaming, tokenized output once complete)
  • Verified on a self-hosted instance (iPhone Safari over remote access): sustained CPU during long code-heavy responses drops noticeably; highlighting appears when the message finishes

@k0n9-devx
k0n9-devx force-pushed the perf/streaming-render branch from 133fbbd to 843dc6a Compare August 8, 2026 15:17
…odeBlock and toolResults map

Streaming updates re-rendered the live message on every SSE message_update,
re-tokenizing the whole growing code block with Prism each time. Render code
fences as plain monospace text while the message is streaming and highlight
once on completion.

Also memoize CodeBlock (unchanged code must not re-run tokenization when the
parent markdown re-renders) and hoist ChatWindow's toolResults Map into a
useMemo keyed on messages so its identity stays stable across streaming
updates.
@k0n9-devx
k0n9-devx force-pushed the perf/streaming-render branch from 843dc6a to fabd15d Compare August 8, 2026 15:17
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