This guide summarizes the main performance levers in the Streaming Markdown V2 pipeline and how to measure them.
Captured in patchStats (automation API + capture summaries):
totalOps,totalMessagesopsPerKB,messagesPerKB(normalized)- per‑op counts (appendLines, setProps, insertChild, etc.)
From the demo automation API and capture summary:
paint avg,p95,max(ms)- goal: keep p95 < ~16ms on target hardware
Long-task observer metrics:
longTask avg,p95,max(ms)- use to detect main‑thread stalls during streaming
Worker boot/parse/highlighter timings and fingerprints:
bootMs,parseMs,highlighterMs- dev fingerprints in worker bundle are captured by
dump-browser-html.ts
StreamingMarkdown accepts scheduling options (see packages/markdown-v2-react/src/streaming-markdown.tsx):
scheduling?: {
batch?: "rAF" | "microtask" | "timeout";
frameBudgetMs?: number;
maxBatchesPerFlush?: number;
lowPriorityFrameBudgetMs?: number;
maxLowPriorityBatchesPerFlush?: number;
urgentQueueThreshold?: number;
adaptiveSwitch?: boolean;
adaptiveQueueThreshold?: number;
}Recommendations
- Use
batch: "rAF"when paint smoothness matters more than throughput. - Use
batch: "microtask"when throughput matters more than paint. - Start with
frameBudgetMs ~ 8–12and tune based on paint p95. - For claim-grade comparisons, prefer the benchmark lab's locked
rAFprofile instead of ad hoc scheduler tuning.
Keep the interpretation strict:
- scheduler changes may move latency and throughput numbers
- they must not change final correctness
- if seeded runs diverge under scheduler variation, treat that as a correctness problem, not a perf footnote
See SCHEDULING_AND_JITTER.md for the current benchmark-mode contract.
Control via features.codeHighlighting:
"incremental"– progressive line‑level highlight, best for long streams"final"– only highlight after block finalizes"live"– re‑highlight on every patch (high CPU cost)
Use liveCodeHighlighting sparingly; it can spike CPU on large blocks.
Large code blocks are windowed to reduce DOM cost.
- Config:
DEFAULT_VIRTUALIZED_CODE_CONFIGinpackages/markdown-v2-react/src/renderer/virtualized-code.tsx - Metrics emitted in capture summaries:
virtualized,totalLines,mountedLines,windowSize
Guidance
- For documents with 500+ line blocks, keep virtualization enabled.
- If you must disable it, set
STREAM_MDX_DISABLE_VIRTUALIZED_CODE=true.
Patch coalescing reduces redundant patch applications (especially lists/tables).
- Metrics available in capture summary:
- input/output counts
- coalesced count
- p95 coalescing duration
If coalescing duration spikes, increase frame budget or reduce streaming rate.
Prewarm languages to reduce first‑highlight latency:
<StreamingMarkdown prewarmLangs={["ts", "json", "bash"]} />Use for docs sites where you know the language set ahead of time.
Use the capture tooling to establish production baselines:
npx tsx scripts/run-markdown-v2-capture.ts \
--lengths 3000,8000,12000 \
--production true \
--verify-replay true \
--screenshot trueCapture summary JSON includes normalized metrics and is used by CI gates.
- Long‑task spikes → reduce live highlighting, lower patch batch size, enable virtualization.
- High opsPerKB → review patch coalescing, list/table splitting, and chunk sizes.
- Slow paint p95 → prefer rAF batching, reduce worker flush rate, defer heavy blocks.
docs/PERF_HARNESS.mddocs/SCHEDULING_AND_JITTER.mddocs/STREAMING_CAPTURE_SOP.mddocs/STREAMING_CAPTURE_TOOL.mddocs/REGRESSION_TESTING.md
Perf gate note:
npm run perf:gatesupports an optional edge-like stress comparison via--candidateEdge/--baseEdge(alias--candidateS6/--baseS6).