Performance Test Guide
A reference for the desktest.net Performance Test. Explains what each metric measures, how to read the tier, and why a VM or remote session (Citrix, RDS, VDI) or a loaded machine scores low. Useful when a user reports "my PC is slow" and you need a quick, honest browser-level read before you decide whether the machine, the session, or the load is the problem.
What does the Performance Test measure?
Four in-browser microbenchmarks that run one after another, with the UI updating between each. No install, no plugin, no clicks during the run. Hit the button, wait about three to four seconds, read the tier. Long loops are chunked so the tab never freezes.
- Processor speed. Runs a fixed, deterministic integer and floating-point workload (a set number of iterations of
Math.sqrt, modulo, and bitwise operations) and times it. Elapsed milliseconds convert to a rough ops/sec-style score. Also readsnavigator.hardwareConcurrency(logical cores). - Graphics and rendering. Measures sustained frame rate over about one second via
requestAnimationFramewhile doing light canvas raster work, and counts dropped frames (any frame gap over ~20 ms). Software rendering and remote sessions show a low frame rate here even when everything else is fine. - Memory. Reads
navigator.deviceMemory(a coarse, rounded, privacy-capped hint, Chromium only) andperformance.memoryJS-heap limits (Chromium only). Browsers do not expose true installed RAM to a web page, so this is the honest ceiling of what is knowable. - Main-thread responsiveness. Chains a series of
setTimeout(0)callbacks and measures actual versus intended delay. Timers that fire far later than the ~4 ms browser clamp mean the event loop is contended: a busy machine, a background scan, or many active tabs.
No network requests leave your browser; every number is computed and shown in JavaScript on the page.
When should I run this?
- "My PC is slow" tickets. The single most-requested help-desk complaint, and usually the vaguest. Have the user open
/perf-test/and send the report. In a few seconds you know whether the browser experience is Fast, Typical, Slow, or Limited, and which area is dragging. - Triaging remote sessions. If the user is on Citrix, RDS, or VDI, a low frame rate is expected and largely outside the endpoint's control. The Limited verdict names this directly so you do not chase a hardware fix that will not help.
- Before and after a cleanup. Run it, close background load and heavy extensions, run it again. If responsiveness and frame rate jump, the problem was load, not hardware.
- Spot-checking a fleet. A quick, repeatable read across machines to find the genuinely underpowered outliers versus the ones that just need a reboot.
Reading the results
Each metric gets a status badge: Pending, Running, Pass, Warn, or Fail. A Slow or low reading shows as Warn and the row expands to show the raw numbers and a short explanation. Nothing here is a hard failure: a Warn means "slower than typical," not "broken."
The verdict panel at the top rolls the four metrics up into one of four tiers:
- Fast - every measured area scored Fast. The machine should feel quick in web apps.
- Typical - no area was Slow. A normal office PC at the browser level.
- Slow - at least one area was Slow (processor, memory, or responsiveness) while the frame rate held up. Usually heavy background load; sometimes genuinely low-end hardware.
- Limited - the frame rate came in Slow. This is the classic signature of a VM or remote session, software rendering, or a heavily loaded host. Browser performance will feel sluggish regardless of the underlying CPU.
The verdict is deliberately a tier plus the raw numbers, not a fake precise "score out of 100." The thresholds are heuristic and the browser APIs are coarse; a tier is as much precision as the data honestly supports.
Copy Diagnostic Report writes a plain-text report to the clipboard: the processor elapsed time and derived score, CPU cores, sustained frame rate and dropped-frame count, reported device memory and JS-heap limit, average and worst timer latency, each metric's tier, and the overall verdict. Paste it into a ticket.
Metric reference and thresholds
All thresholds below are rough heuristics chosen to separate "clearly fine" from "clearly struggling," not calibrated hardware limits. Treat borderline readings as borderline.
Processor speed
The workload is fixed and identical every run, so the elapsed time is comparable across machines. Faster is lower elapsed time. Buckets: Fast when the fixed workload finishes in about 220 ms or less, Typical up to about 550 ms, Slow beyond that. The derived "M iterations/sec" figure is just the inverse of the elapsed time, shown because it reads more naturally than milliseconds. hardwareConcurrency reports logical cores (physical cores times SMT/hyper-threading); it is a capacity hint, not a speed measurement. A slow reading with plenty of cores usually means per-core throttling or heavy background load, not a lack of cores.
Graphics and rendering
Sustained frame rate over roughly one second. Buckets: Fast at about 50 fps or higher, Typical from about 25 fps, Slow below that. On a 120 Hz display the reading can exceed 60 fps; that is still Fast. A dropped/janky frame is any frame whose gap exceeds ~20 ms; a handful is normal, a lot points to a busy main thread or software compositing. This is the most sensitive metric for remote sessions: a browser inside Citrix, RDS, VDI, or a VM sees the host's virtual graphics stack rather than a local GPU and typically renders in software, which caps the frame rate well below a physical install.
Memory
navigator.deviceMemory is a deliberately coarse hint: it is rounded to a power of two and capped at 8 GB for privacy, so a 32 GB workstation and a 12 GB one both report 8. Treat it as "at least this much," not an exact figure. Buckets: Fast at 8 GB (the cap), Typical at 4 GB, Warn/low at 2 GB or below. performance.memory reports the JavaScript heap limit, not system RAM, and only in Chromium; where it is missing the row says so plainly. If neither is exposed, the row is marked Pass with a note that this is a browser limitation, not a fault of the machine, and memory simply does not contribute to the verdict.
Main-thread responsiveness
Chained setTimeout(0) callbacks are clamped by the browser to about 4 ms once nested, so ~4 ms is the expected floor even on an idle machine. What matters is how far above that floor the timers actually fire. Buckets: Fast when the average delay is about 10 ms or less and the worst is about 40 ms or less; Typical up to roughly 25 ms average and 150 ms worst; Slow beyond that. High latency here means the event loop is contended right now: another application pegging the CPU, an antivirus or update running, or many busy tabs. It is the most time-sensitive metric, so re-run after closing background load before concluding the hardware is the limit.
For IT admins
"Slow PC" is the vaguest and most common complaint you will field, and most of the time the hardware is fine. Use this tool to split the ticket fast: is it the machine, the session, or the load?
Rule out load first. A Slow responsiveness reading with a healthy processor score almost always means something else is eating the CPU. Check Task Manager for a runaway process, a Windows Update install, a full antivirus scan, or a sync client re-indexing. Reboot, let it settle, and re-run. Load-driven "slowness" evaporates; hardware-driven slowness does not.
Citrix / RDS / VDI. A browser inside a published session sees the session host's virtualized graphics, not the local thin client's GPU. Frame rate will read Slow and the verdict will say Limited even on a well-provisioned endpoint, because the rendering path really is slower. This is expected and is a session-design question (host GPU allocation, HDX / Browser Content Redirection, session density), not an endpoint repair. Do not swap a thin client to fix a Limited verdict caused by the session.
Genuinely underpowered hardware. A Slow processor score that stays Slow after a reboot with nothing else running, especially alongside a low device-memory reading, is the honest "this machine needs replacing" signal. Capture the diagnostic report on a few representative machines to build the refresh case with numbers rather than anecdotes.
Battery and power plans. Laptops on battery or on a "power saver" plan throttle the CPU aggressively; the processor and responsiveness scores drop accordingly. If a user reports slowness only when unplugged, that is the power plan, not the machine. Check the plan before escalating.
Browser hygiene. Heavy extensions, hundreds of open tabs, and a bloated profile all drag responsiveness and frame rate. A clean profile or a disabled extension set is a free before/after test.
Behind the scenes
The processor step runs a fixed number of iterations of a mixed integer and floating-point loop and sums only the time spent inside the compute chunks, excluding the yields between them, so the score reflects raw compute and not scheduling gaps. The accumulator feeds forward every iteration and is retained at the end so the optimizer cannot eliminate the loop as dead code. The loop is split into chunks with a setTimeout(0) yield between each, which keeps the tab responsive during the run at the cost of a few milliseconds of overhead that the timing deliberately excludes.
The graphics step times the gaps between requestAnimationFrame callbacks over about one second. The first gap (start to first paint) is dropped from the pacing and jank statistics so warm-up does not count as a dropped frame. Light canvas raster work runs each frame on an off-DOM canvas so nothing flashes on screen while still giving the raster path something to do; the frame pacing itself is what is measured. If requestAnimationFrame is somehow unavailable, the step degrades to an informational row rather than failing.
The memory step only reads values; it allocates nothing and forces no garbage collection. navigator.deviceMemory and performance.memory are both Chromium-only and both coarse by design, which is why the tool labels exactly what each one is and what it is not (a JS-heap ceiling is not system RAM) rather than implying more precision than the platform provides.
The responsiveness step chains its timers (each callback schedules the next) rather than scheduling them all at once, so it measures serialized event-loop latency under the browser's nested-timer clamp instead of a burst that the browser would batch. Every metric is wrapped so a missing or throwing API degrades to an informational row and never crashes the run.
Nothing leaves the browser. All measurements run in JavaScript on the page and the numbers are computed locally. View source to verify. The diagnostic report is plain text built in memory and copied to the clipboard via navigator.clipboard.writeText with a synthetic textarea fallback for browsers that block clipboard write.
Related
- Performance Test - the tool itself
- Browser Test Guide - checks whether the browser itself is ready for modern web apps
- Network Test Guide - the equivalent for connectivity and DNS
- About desktest.net
- Help: getting started
- desktest.net home
Elsewhere on the web:
- web.dev: the RAIL performance model - why response, animation, and idle latency are the numbers users actually feel.
- MDN: navigator.deviceMemory - what the device-memory hint reports and why it is rounded and capped.