Skip to content

perf(webui): fix streaming first-part display lag and optimize render…#4

Merged
duguwanglong merged 1 commit intomainfrom
perf/webui-streaming-optimization
Mar 30, 2026
Merged

perf(webui): fix streaming first-part display lag and optimize render…#4
duguwanglong merged 1 commit intomainfrom
perf/webui-streaming-optimization

Conversation

@xiami762
Copy link
Copy Markdown
Contributor

@xiami762 xiami762 commented Mar 30, 2026

Changes:

webui/src/hooks/useSessions.ts

  • Extract applyMessagePartUpdate as a testable pure function
  • Add knownPartIdsRef to distinguish new-part creation from content deltas
  • New parts (first appearance): direct setMessages — renders immediately
  • Known-part deltas: startTransition — allows React to batch low-priority
  • Evict part IDs from registry on message finish to prevent memory leak
  • Clear registry on session change via useLayoutEffect

webui/src/components/common/SessionChat.tsx

  • Wrap ChatMessageBubble with React.memo + O(1) comparator
  • Replace ReactMarkdown + rehype imports with StreamingMarkdown component
  • Switch scrollIntoView from 'smooth' to 'instant' (eliminates queuing)

webui/src/components/common/StreamingMarkdown.tsx (new)

  • rAF-throttled Markdown rendering: same-frame deltas coalesce into one ReactMarkdown parse
  • On streaming=false: cancel pending rAF and flush final content immediately

webui/src/hooks/useSSE.ts

  • Guard all console.log/warn with import.meta.env.DEV

flocks/session/streaming/stream_processor.py
flocks/server/routes/event.py

  • Downgrade hot-path log calls from info to debug

Tests:

  • webui/src/hooks/useSessions.test.ts (new): 13 tests covering applyMessagePartUpdate edge cases and updateMessagePart behaviour
  • webui/src/components/common/StreamingMarkdown.test.tsx (new): 6 tests covering rAF throttling and streaming-complete flush

… pipeline

Problem:
- "Thinking" and "streaming" indicators appeared with noticeable delay
  because startTransition deferred even structural state changes (new
  part creation), pushing parts.length 0→1 flip to an idle frame
- flushSync on every SSE chunk blocked the main thread
- ReactMarkdown was re-parsed on every chunk with visual plain-text→MD jump
- Verbose console.log and info-level backend logs added overhead

Changes:

webui/src/hooks/useSessions.ts
- Extract applyMessagePartUpdate as a testable pure function
- Add knownPartIdsRef to distinguish new-part creation from content deltas
- New parts (first appearance): direct setMessages — renders immediately
- Known-part deltas: startTransition — allows React to batch low-priority
- Evict part IDs from registry on message finish to prevent memory leak
- Clear registry on session change via useLayoutEffect

webui/src/components/common/SessionChat.tsx
- Wrap ChatMessageBubble with React.memo + O(1) comparator (aligned with
  Open WebUI fast-path): skips re-render when isActive, parts.length,
  finish, and last-part text/thinking/state are unchanged
- Replace ReactMarkdown + rehype imports with StreamingMarkdown component
- Switch scrollIntoView from 'smooth' to 'instant' (eliminates queuing)

webui/src/components/common/StreamingMarkdown.tsx  (new)
- rAF-throttled Markdown rendering: same-frame deltas coalesce into one
  ReactMarkdown parse, matching Open WebUI's Markdown.svelte mechanism
- On streaming=false: cancel pending rAF and flush final content immediately

webui/src/hooks/useSSE.ts
- Guard all console.log/warn with import.meta.env.DEV

flocks/session/streaming/stream_processor.py
flocks/server/routes/event.py
- Downgrade hot-path log calls from info to debug

Tests:
- webui/src/hooks/useSessions.test.ts (new): 13 tests covering
  applyMessagePartUpdate edge cases and updateMessagePart behaviour
- webui/src/components/common/StreamingMarkdown.test.tsx (new): 6 tests
  covering rAF throttling and streaming-complete flush

Made-with: Cursor
@xiami762 xiami762 requested a review from duguwanglong March 30, 2026 05:21
@duguwanglong duguwanglong merged commit a733610 into main Mar 30, 2026
2 checks passed
@duguwanglong duguwanglong deleted the perf/webui-streaming-optimization branch March 30, 2026 05:49
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.

2 participants