inputprobe

Polling, frames and coalesced events

Every tool on this site rests on one technical fact: a browser does not hand a page mouse input as it happens. It batches it. This page walks the whole pipeline, from the sensor to your event listener, because the difference between reading the batch and counting the batches is the difference between measuring your mouse and measuring your monitor. The polling rate test is the working demonstration; this is the explanation.

Stage one: the device reports

A mouse does not stream continuous motion. It accumulates counts from its sensor and sends a report at a fixed interval it controls: every 8 milliseconds at 125 Hz, every 1 millisecond at 1000 Hz. That interval is the polling rate, set by the mouse and its software. Each report says how far the mouse moved since the last one, which buttons are down, and what the wheel did. Between reports the computer knows nothing new; a mouse that reports at 125 Hz cannot be asked for more, whatever software runs above it.

The operating system receives those reports, moves the cursor, and passes them to whichever application has focus. Up to this point nothing is lost: a 1000 Hz mouse delivers a thousand distinct reports per second into the input queue.

Stage two: the browser draws in frames

A browser paints the page in step with the display, typically 60, 120 or 144 times per second, and it wants event handling to line up with painting: there is no point running your mousemove handler five hundred times if the page can only show the result sixty times. So the browser gathers every device report that arrived since the last frame and, once per frame, dispatches a single mousemove or pointermove event carrying their combined movement.

This is called coalescing, and for almost every purpose it is the right behaviour: scrolling, dragging and drawing stay smooth, and pages do less work. But it means the EVENT rate a page observes is the frame rate. A tester that counts events per second is counting frames per second, and its number will change when you plug the same mouse into a different monitor, which should be impossible for a property of the mouse.

Stage three: the batch is still there

The batching is lossless. In every current engine, each pointermove event exposes the individual device reports it absorbed through getCoalescedEvents(), each with its own position, movement deltas and timestamp. The frame-aligned event is an envelope; the reports are inside it, and opening the envelope recovers what the device actually sent: at 1000 Hz on a 60 Hz display, roughly sixteen or seventeen coalesced samples inside every dispatched event.

Timing those inner samples is how the polling rate test reads the mouse instead of the screen. It is also why the numbers on this site survive a monitor change: the envelope arrives at the display's pace, but the timestamps inside it belong to the device.

What the timestamps can and cannot say

Browsers deliberately blur high resolution time. Event timestamps are quantised, commonly to 100 microseconds and more coarsely in some configurations, and several coalesced samples can share one clock tick at high polling rates. An estimator that ignores this reads structure into rounding. The one used here treats quantisation as a known distortion, measures only continuous stretches of movement, and refuses to print a number when too little clean signal survives; the methodology page states what has been validated against physical hardware and what against simulated streams only.

The counter-example: devices with no events at all

The event pipeline above exists for mice, keyboards and touch. A game controller gets none of it: the browser keeps a copy of the controller's state and lets a page read that copy whenever it likes. There is no batch, no timestamps and nothing to coalesce, so a page can only report how often the copy changed between its own reads. That is a property of the browser and the machine, not the controller, which is why the gamepad tester refuses to call its refresh figure a polling rate. Comparing the two pipelines is the cleanest way to see what coalesced events actually provide: per-report timing that the gamepad path simply does not have.

Why any of this matters

For desktop work, it does not: coalescing exists precisely so ordinary pages never think about it. It matters when the question is about the device itself. Verifying a gaming mouse actually runs at its advertised rate, checking whether a wireless mouse throttles on battery, or catching a USB hub that caps reports: all of these need the inner samples, and every online tester that skips them is reporting your display's refresh rate with a mouse-shaped label on it.

See it on your own hardware: the polling rate test lets you watch its events counter outrun the frames your display draws, the DPI test uses the same coalesced deltas to count movement, and the keyboard tester reads key events through the identical discipline.