Repository navigation
Idea: let the host declare a rendering priority for embedded conversations (multi-pane streaming drops to ~24fps) #12559
Awenforever
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Proposal: a rendering-priority hint for embedded conversations
Summary
DeepSeek Harness can host several conversations at once (this plugin does it with 2–4 panes),
but the shipped chat has no way to tell it "this transcript is in the background". Every pane
pays the full per-chunk cost, so four panes that stream at the same time drop to roughly 14–28 fps
on a modest machine even though the plugin's own code accounts for 0.6 % of the profile.
The ask is small and backwards compatible: let the host declare a rendering priority for the
conversation it embeds, and let the chat use it to coalesce work. Nothing about the visual
result changes — text still appears, panes still scroll, only the cadence is allowed to be lower.
Evidence
Measured on Windows 11 (DSH Desktop 0.2.2-rc.1, Electron renderer, 1530×851), 4 panes bound to
4 sessions, all four streaming a long answer, 60 s window:
A 12 s CPU profile during the streaming case, grouped by self time of the sampled nodes:
(program)— layout, paint, composite, GC@deepseek-ai/dsh-client-ui-chat+ui-conversation(renderEntry,ConversationContent,onScroll,scrollMetrics)Two things follow. First, the plug-in side is not the problem and cannot fix it. Second, the cost
is dominated by layout and paint of a growing transcript, which is exactly what a host can
influence — but only the chat knows how to coalesce it.
The transcript virtualizer is already well configured (
directDomUpdates: true,useScrollendEvent: true,overscan: 3), so the remaining per-chunk work is the growing turnitself: the streaming turn's height changes on almost every chunk, which invalidates layout for
that turn and re-runs the offset bookkeeping (
scrollMetricsshowed up as 352 ms of self time inone 14 s profile — about 2.5 % of sampled time, in a run where four panes were streaming).
Proposal
Add an optional field to the existing
conversation.contentfactory props, next tovariant: 'embedded'andphase:Semantics, all opt-in and invisible when omitted:
foreground(default) — today's behaviour.background— the chat may coalesce renders: commit at most once per animation frame or pera small interval (e.g. 100–250 ms), whichever the implementation prefers, and skip intermediate
markdown re-parses. The transcript stays mounted, keeps its scroll anchoring, and still shows
the growing text — it simply updates in slightly larger steps.
The host already knows which panes are focused; a plugin can pass
backgroundfor the rest andswitch a pane to
foregroundthe instant it gains focus. That gives every host (multiview,future tiled layouts, embedded previews) the same lever without any of them touching chat internals.
Optional extras that would help equally and are cheap to reason about:
animation frame. Four panes would still cost four renders per frame, but not four per token.
content-visibility: auto(orcontain: content) on messages rather than turns, so messagesscrolled out of the local pane viewport skip layout entirely. Our measurement of
contain: stricton the pane container showed no gain (59.2 vs 58.5 fps — noise), so the usefulgranularity is the message, not the pane.
What this does not fix
Anything that forces a full layout of a huge turn remains linear in turn size; four panes of very
long answers will stay heavier than one. The proposal reduces how often that happens, not the
per-occurrence cost.
Reproduction
The multiview plugin is public: https://github.com/Awenforever/dsh-multiview (npm
dsh-multiview).Open two or more panes, bind four sessions, send a long-form prompt to all four at once, and sample
requestAnimationFrameintervals plusPerformanceObserver({ type: 'longtask' }).All reactions