What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
LLM chat feels slow for two fundamentally different reasons: the model or network may delay the first token, or the browser may spend so much time rendering each arriving delta that the interface freezes. Fixing the wrong side wastes time. Measure time to first token (TTFT), completion time, and token velocity on the server, then measure React commit and browser paint work on the client. Use semantic streaming events, keep generation concise, cancel abandoned requests, buffer deltas, and publish transcript updates on a controlled schedule. Isolate urgent controls from the transcript and apply React optimizations only after profiling.
stream: true improves time to first token and perceived responsiveness; it does not shorten the time needed to generate the complete response. A smooth implementation therefore treats transport, scheduling, React rendering, and browser painting as separate stages.
As an Amazon Associate I earn from qualifying purchases.
Why does an LLM stream start late or appear to freeze?
“Streaming lag” is not one measurement. A request can wait before the first event, deliver tokens quickly but trigger expensive React commits, or finish promptly while Markdown parsing and painting block the main thread. The visible symptom is similar, but each cause needs a different fix.
Upstream delay: time to first token
TTFT includes the time spent creating the request, queuing it, processing the prompt, and producing the first output event. Larger prompts, longer requested answers, multiple sequential model calls, and unnecessary server-side work all increase the wait. OpenAI’s latency guidance emphasizes processing tokens faster, generating fewer output tokens, using fewer input tokens, reducing request count, parallelizing independent work, and avoiding an LLM when a conventional interface would be faster.
#1 Best Overall
- CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
- WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
- A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
Downstream delay: rendering and painting
Once deltas arrive, every state update can invalidate components, run reconciliation, parse rich text, lay out DOM, and paint pixels. If the transcript update causes the entire application tree to render, keystrokes and the cancel button compete with token processing. Replacing a whole text node or document for each chunk can also make the browser repeatedly remove and recreate work that could have been updated incrementally.
Both pipelines can be slow
A slow first token and a render storm can coexist. Do not infer a model problem from a sluggish cursor, and do not infer a React problem from a long blank interval before the first event. Capture timestamps for both paths before changing architecture.
How should I measure the bottleneck?
Collect server percentiles and client timings for the same request. Averages hide the slow tail; compare P50, P75, and P95 so an occasional queueing or rendering spike is visible.
1. Instrument the server and API path
- Record the timestamp immediately before sending the model request.
- Record the first event or first token. The difference is TTFT.
- Record every subsequent event or enough information to calculate token velocity.
- Record the final event and total request duration.
- Record output-token count and the request identifier that lets you match server data to a browser session.
- Report P50, P75, and P95 for TTFT and total duration separately. A low TTFT with a long total time means generation is lengthy; a high TTFT with a short completion means the initial wait dominates.
When using the Responses API, consume semantic server-sent events rather than treating the stream as an undifferentiated text socket. Text fragments arrive as response.output_text.delta; handle the completion event explicitly so the UI can close its loading state even when the last delta is empty.
2. Measure React commits
Wrap the transcript subtree in React’s <Profiler>. Its callback exposes actualDuration, baseDuration, startTime, and commitTime. actualDuration is the work performed for the current commit; baseDuration estimates the cost of rendering the subtree without memoization. Compare those values while a response is idle, while it streams, and after it finishes.
import { Profiler } from 'react';
function onRender(
id,
phase,
actualDuration,
baseDuration,
startTime,
commitTime
) {
performance.measure(`react:${id}:${phase}`, {
start: startTime,
end: commitTime
});
console.log({
id,
phase,
actualDuration,
baseDuration,
startTime,
commitTime
});
}
<Profiler id="transcript" onRender={onRender}>
<Transcript messages={messages} />
</Profiler>
Profiling itself adds overhead, so use it deliberately during diagnosis and limit or remove it from production builds. A large actualDuration on every delta is a client-side render problem even when TTFT is excellent.
3. Inspect browser work
Chrome DevTools’ Performance panel shows scripting, style calculation, layout, and paint. Enable paint flashing to see whether token arrival repaints unrelated controls. Look for repeated full-text replacement, repeated Markdown parsing, long JavaScript tasks, and layout work that grows with transcript length. Chrome’s streaming-rendering guidance warns that repeatedly replacing textContent or innerText for every chunk creates unnecessary removal and replacement work; incremental parsing and rendering keep browser work bounded.
Rank #2
- CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
- SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
4. Classify the result
| Observation | Likely bottleneck | First action |
|---|---|---|
| High TTFT; short React commits | Model, queue, prompt, network, or backend preprocessing | Reduce input/output work, remove serial calls, and inspect server percentiles. |
| Low TTFT; long commits or paint tasks | React render storm or browser rendering | Buffer deltas, isolate the transcript, and profile the largest subtree. |
| High TTFT and long commits | Both pipelines | Fix upstream and client paths independently; do not expect one change to solve both. |
| Fast commits but visible pauses between events | Transport, backend buffering, or event scheduling | Timestamp each server event and each client receipt before changing React code. |
How do I reduce streaming latency on the model and server?
Optimize the path before the first event and the amount of work required after it. Streaming improves responsiveness, but it cannot make the model generate fewer tokens unless you ask for fewer tokens.
Use semantic streaming events
For new OpenAI integrations, prefer the Responses API stream. Route response.output_text.delta fragments into a stream store and treat the completion event as the authoritative end of generation. Explicit event handling prevents a client from waiting for a delimiter or guessing that the response ended because no data arrived briefly.
Limit output deliberately
Set a stopping limit appropriate to the task and ask for concise output when a shorter answer is sufficient. Output generation is a major latency contributor. A long answer streamed quickly can still take longer overall than a concise answer returned at the same token velocity.
Reduce input and request overhead
- Send only the conversation and instructions the model needs for this turn; avoid duplicating large context blocks.
- Combine work that can be done in one request when that is correct, but do not serialize independent calls merely because they are convenient to implement.
- Parallelize independent retrieval, classification, or metadata work where correctness permits, then assemble the result before or during streaming.
- Use a conventional UI for deterministic operations such as filtering, sorting, or form validation instead of asking an LLM to perform them.
Stream through the backend when processing is required
If your server must moderate, translate, redact, or transform output, forward useful chunks as they become available instead of waiting for the complete model response. The backend should preserve ordering, propagate completion and error states, and avoid turning a streaming model call into a buffered request.
Cancel abandoned generations
When a user submits a new prompt, closes the page, or presses Cancel, abort the model request and stop downstream parsing. The exact cancellation API depends on the transport and SDK; verify it against the current SDK documentation. Also handle client disconnects so a generation that no longer has a listener does not continue consuming model and server capacity.
How do I stop React from rendering on every token?
Do not publish every network delta directly to top-level React state. Keep a mutable accumulation buffer or stream store, then publish snapshots on a controlled schedule. The transcript can update frequently enough to feel live without forcing the entire application tree to reconcile for every fragment.
Buffer deltas and schedule snapshots
The stream reader should append text to a buffer. A scheduler can publish once per animation frame or at a measured time interval. There is no universal safe cadence: tune it against your measured commit duration, output format, device class, and the smoothness users perceive.
Recommended Free Tools
Rank #3
- Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
- Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
- Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
- In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
- Ultra-thin bezels: Maximize your viewing experience with thin bezels.
const buffer = { text: '', scheduled: false };
function receiveDelta(delta) {
buffer.text += delta;
if (buffer.scheduled) return;
buffer.scheduled = true;
requestAnimationFrame(() => {
buffer.scheduled = false;
transcriptStore.publish({ text: buffer.text });
});
}
The store should expose a stable snapshot to the transcript. Controls such as the prompt input, Cancel button, and connection indicator should subscribe to their own small pieces of state rather than to every text mutation.
Keep urgent UI separate from transcript work
Place the input, submit button, cancellation control, and connection status in components that do not receive the entire transcript as a prop. A new token should not cause the input caret, toolbar, or navigation tree to re-render. This local isolation often produces a larger improvement than memoizing dozens of unrelated components.
Use React 18 automatic batching
React 18 batches updates from promises, timeouts, and native event handlers, reducing multiple state updates to fewer renders. Batching is helpful, but it does not make an expensive render cheap. If one batched update still parses a long Markdown document and repaints the full transcript, buffering and component boundaries remain necessary.
Use transitions for non-urgent work
useTransition marks an update as background work that React may interrupt when an urgent interaction arrives. It can help with an expensive transcript view or derived search result, but it must not control a text input. Keep input state synchronous so typing and cursor movement stay responsive.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchconst [isPending, startTransition] = useTransition();
function publishTranscript(nextSnapshot) {
startTransition(() => {
setTranscript(nextSnapshot);
});
}
Use this only after measuring. A transition changes scheduling priority; it does not reduce the amount of parsing, reconciliation, or painting the update performs.
Memoize after profiling
memo can skip a child when its props are unchanged, but it is not a guarantee. It loses much of its value when each parent render creates new object or function props. Pass stable primitives where possible, use stable callbacks when they are genuinely needed, and verify the result in the Profiler.
Remove unnecessary Effect-driven updates
Chains of Effects that compute derived state and then set more state are a common source of repeated renders. Derive values during render when the calculation is cheap, or cache a genuinely expensive calculation with useMemo and stable dependencies. Do not add memoization to compensate for an Effect loop that should be removed.
Rank #4
- CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
- SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
- MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
- KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
- INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient
Should I debounce or throttle streamed tokens?
For a live transcript, scheduled batching is usually more predictable than debouncing. Debouncing waits for silence and can make the answer appear frozen whenever deltas arrive continuously; throttling or animation-frame batching guarantees periodic progress while bounding update frequency.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →| Policy | Behavior | Best fit | Risk |
|---|---|---|---|
| Every delta | Publishes immediately | Very small plain-text views with measured low commit cost | Render storms as output rate or transcript size grows |
| Animation-frame batching | Publishes at the browser’s paint schedule | Interactive plain text where visual freshness matters | Still expensive if each frame parses the entire document |
| Time-window batching | Publishes at a measured interval | Heavy Markdown or code rendering, especially on slower devices | Long intervals feel less live |
| Debouncing | Waits for a quiet period | Finalization work after streaming stops | Continuous output may never show intermediate snapshots |
Choose the interval from measurements, not a copied “magic” number. Record commit duration and perceived responsiveness on representative devices, then shorten the interval only while commits remain comfortably below the available frame budget.
How should I render plain text, Markdown, and code safely?
Plain text is the cheapest format: keep one bounded text node or a small set of nodes and update the current message incrementally. Avoid rebuilding the entire transcript for every delta.
Plain text
Store completed messages separately from the in-progress message. Render stable completed messages without touching them, and update only the active message snapshot. This limits reconciliation work as the conversation grows.
Markdown and code
Markdown needs incremental parsing so the parser does not restart over the entire response on every chunk. Code blocks and tables may be incomplete while streaming, so the renderer must tolerate unfinished constructs and replace only the affected region when a block closes.
Sanitize parsed output before inserting it into the DOM. Streaming rich text increases the number of intermediate states, so sanitization must run on each inserted or updated fragment, not only on the final answer. Chrome for Developers specifically recommends a streaming Markdown parser to avoid unnecessary browser work.
Long transcripts
When conversations become large, keep completed messages structurally stable and consider rendering only the visible portion. Do not add virtualization blindly: measure whether the cost is reconciliation, parsing, layout, or paint first, then choose the narrowest change that addresses that cost.
Best Value
- 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
- 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
- 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.
What should a robust streaming component architecture look like?
Separate transport state from rendering state. The transport reader owns the connection and cancellation; a stream store owns the mutable buffer; a scheduler publishes snapshots; the transcript renders those snapshots; controls subscribe only to connection and cancellation state.
- Transport layer: starts the request, reads semantic events, handles errors, and aborts on cancellation or disconnect.
- Accumulator: appends each output delta without calling React state setters for every event.
- Scheduler: publishes a snapshot on an animation frame or measured interval and flushes the final snapshot on completion.
- Transcript view: receives the snapshot and stable presentation props; completed messages should not be reparsed unnecessarily.
- Controls: subscribe to status, error, and cancellation state, not to every text mutation.
- Diagnostics: enable the Profiler and browser traces during investigation, then limit profiling overhead in production.
async function consumeResponse(response, store, signal) {
const reader = response.body.getReader();
const decoder = new TextDecoder();
try {
while (true) {
const { value, done } = await reader.read();
if (done) break;
const text = decoder.decode(value, { stream: true });
for (const event of parseServerSentEvents(text)) {
if (event.type === 'response.output_text.delta') {
store.append(event.delta);
} else if (event.type === 'response.completed') {
store.complete();
}
}
}
} finally {
reader.releaseLock();
}
}
The parser in this example must preserve partial lines between network reads; an SSE event can be split across byte chunks. Keep that parser independent from React so transport fragmentation cannot trigger extra component renders.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →How do I troubleshoot a streaming chat UI that still freezes?
Work from timestamps to the narrowest expensive operation. Change one variable at a time so an improvement can be attributed correctly.
- Confirm event arrival: log request start, first event, each client receipt, completion, and abort. If the browser receives nothing during the blank period, inspect upstream work rather than React.
- Compare TTFT and commit time: high TTFT points upstream; high commit or paint time points to the client.
- Disable rich rendering temporarily: show plain text to determine whether Markdown, syntax highlighting, or sanitization dominates.
- Freeze completed messages: render only the active message as mutable. If commit time falls, the transcript was rebuilding stable content.
- Profile parent boundaries: look for application-level state that changes on every delta and causes unrelated components to render.
- Test cancellation: start a response, navigate away, and submit another prompt. Verify that the old reader, parser, scheduler, and server request all stop.
- Recheck percentiles: compare P50, P75, and P95 after the change. A better median with a worse tail may indicate device- or prompt-specific regressions.
Which optimization should I choose first?
Choose based on the measured stage, not on the popularity of a technique.
| Measured symptom | Start with | Do not start with |
|---|---|---|
| TTFT dominates | Shorter prompts and outputs, fewer or parallel requests, backend streaming | Memoizing transcript rows |
| Every delta causes a long commit | Buffering, a scheduler, isolated controls, and Profiler-guided component boundaries | Increasing model speed |
| Commit is short but paint is long | Incremental DOM updates, smaller rich-text regions, and browser trace analysis | More React state batching alone |
| Typing becomes laggy during streaming | Separate input state and, if needed, transition non-urgent transcript updates | Putting the input inside the streamed state tree |
| Only Markdown responses freeze | Incremental parsing and per-fragment sanitization | Reparsing the complete response on every event |
What does a successful fix look like?
A successful fix is observable in both telemetry and interaction. The first event arrives when the server metrics say it should, transcript commits occur on the chosen schedule, the input remains responsive, and cancellation releases work promptly. Record the same TTFT, total duration, output-token count, token velocity, React durations, and browser trace categories before and after each change. No authoritative source establishes a universal token-update cadence, maximum render count, or guaranteed frame rate; your application’s measurements are the appropriate acceptance criteria.
Frequently Asked Questions
Does stream: true make the model generate the answer faster?
No. It lets the client receive tokens as they become available, reducing time to first token and improving perceived responsiveness. The complete output still requires the model’s normal generation time, so shorten unnecessary output when total completion time matters.
Free tools Windows power users keep installed
One-click scans. No signup required.
Why does the first token arrive quickly but the screen update late?
The network reader may be receiving data while a scheduler, parser, or long JavaScript task delays publication and painting. Compare the timestamp of client receipt with the timestamp of the React commit; that pair reveals whether the delay is between transport and rendering rather than in the model.
How can I verify that cancellation really stopped an old response?
Give each generation a unique identifier and log abort, reader closure, parser shutdown, and server disconnect for that identifier. Starting a second prompt should leave no further deltas from the first generation in the store.
What is the safest way to stream untrusted Markdown?
Parse incrementally, tolerate incomplete blocks, and sanitize every fragment before DOM insertion. Keep the sanitizer in the rendering path for intermediate chunks instead of assuming that only the final completed answer needs checking.
Should I leave React Profiler enabled in production?
Use it for targeted diagnosis because profiling adds overhead. Capture representative traces in a controlled build, then disable or narrowly gate the profiler after you have identified the expensive subtree and verified the fix.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsQuick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

