You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Perf] Pointer moves: screen-CTM read and interaction-point rebuild on every move, and no early-input option #203
updateFocus returns early on an unchanged point only after all of that (renderer.ts:545-555).
Measured in Chrome (radar, 3 polygons, custom focus.resolve, 300 moves inside one polygon, 3 runs): 0.13-0.18 ms per move in the handler. The strategy itself is 0.004-0.011 ms. The same chart drawn with per-polygon mouseenter costs 0.035-0.05 ms.
B. No way to use earlier pointer input
Chrome aligns pointermove to the frame. On a line chart at 1440 px, about 8 ms of the 9.7 ms median from input to the next painted frame is this wait. pointerrawupdate arrives 0.5-2 ms after the input, but the renderer only listens to pointermove. Driving setControlledFocus from it makes the owner 'controlled', so pointer leave no longer clears focus (see the comment on #189).
Proposal
A: cache the inverse CTM until a resize or scene update, and let a strategy say the pointer is still inside the current focus (for example contains(x, y)) so the controller skips the rebuild.
B: an option such as pointerEvent: 'pointermove' | 'pointerrawupdate' (falling back where unsupported), or a public method that applies a pointer sample with the same leave and tooltip handling as the move handler.
Related: #190 (what a strategy can see). Checked against 57774e14a1a86081eddb3a23523724a40da05640 (v1.1.0).
changed the title [-]Pointer moves: every move re-reads the screen CTM and rebuilds the interaction points, and focus waits for the aligned `pointermove`[/-][+][Perf] Pointer moves: screen-CTM read and interaction-point rebuild on every move, and no early-input option[/+]on Oct 13, 2026
Thanks @toomingos, the viewport-filter part is merged in #225. It skips mark ownership lookup for points already inside the viewport and avoids reading unrelated channel values for offscreen points.
In seven paired Chromium trials, 200 filters of 1,000 points improved from 17.1 to 1.4 ms for visible points and 16.8 to 6.3 ms for offscreen points. This measures filtering only, not total pointer latency. The fix passes 2,237 tests, maintained example builds, and a 432-case ownership matrix in Chromium, Firefox and WebKit. The measured bundle costs were approved, with maximum increases of 0.009 kB gzip and 0.117 kB Brotli across the entry-point audit.
Keeping this open for the screen-CTM work and early-input option. The patch Changeset is merged, but it has not been published to npm yet.
I checked the proposed resize/scene-update cache in Chromium, Firefox and WebKit. It would leave stale pointer coordinates in all three:
Translating an ancestor by (40, 30) changes a client (100, 100) sample to chart (60, 70).
Adding a 75 px sibling above the chart changes it to (100, 25).
Scrolling the page by 50 px changes it to (100, 150).
The SVG's width and height stay unchanged in each case, and no chart scene update is needed. A cache that only watches chart size and scene updates keeps returning (100, 100).
So the remaining coordinate optimization needs to handle ancestor layout, transforms and scrolling too. I'm keeping the fresh matrix read for now. This does not affect the viewport-filter improvement already merged in #225.
Activity
[-]Pointer moves: every move re-reads the screen CTM and rebuilds the interaction points, and focus waits for the aligned `pointermove`[/-][+][Perf] Pointer moves: screen-CTM read and interaction-point rebuild on every move, and no early-input option[/+]tannerlinsley commentedon Oct 14, 2026
Thanks @toomingos, the viewport-filter part is merged in #225. It skips mark ownership lookup for points already inside the viewport and avoids reading unrelated channel values for offscreen points.
In seven paired Chromium trials, 200 filters of 1,000 points improved from 17.1 to 1.4 ms for visible points and 16.8 to 6.3 ms for offscreen points. This measures filtering only, not total pointer latency. The fix passes 2,237 tests, maintained example builds, and a 432-case ownership matrix in Chromium, Firefox and WebKit. The measured bundle costs were approved, with maximum increases of 0.009 kB gzip and 0.117 kB Brotli across the entry-point audit.
Keeping this open for the screen-CTM work and early-input option. The patch Changeset is merged, but it has not been published to npm yet.
tannerlinsley commentedon Oct 14, 2026
I checked the proposed resize/scene-update cache in Chromium, Firefox and WebKit. It would leave stale pointer coordinates in all three:
(40, 30)changes a client(100, 100)sample to chart(60, 70).(100, 25).(100, 150).The SVG's width and height stay unchanged in each case, and no chart scene update is needed. A cache that only watches chart size and scene updates keeps returning
(100, 100).So the remaining coordinate optimization needs to handle ancestor layout, transforms and scrolling too. I'm keeping the fresh matrix read for now. This does not affect the viewport-filter improvement already merged in #225.