leeoniya / uPlot

📈 A small, fast chart for time series, lines, areas, ohlc & bars
MIT License
8.48k stars 370 forks source link

fix mouse interaction performance for 2,000 series #932

Closed leeoniya closed 2 months ago

leeoniya commented 2 months ago

this is a retro issue to illustrate the performance gains of the new cursor.points.one: true setting with a large amount of series (2k series * 1k points each). the commits were:

uPlot currently draws live cursor hover points using dom elements to avoid clearing and redrawing the main canvas on every mousemove event. this strategy may change in the future to utilize a second canvas, but that's a longer-term project: https://github.com/leeoniya/uPlot/issues/922. anyways, the DOM method works well for a sane amount of series (< 100). however, there are users of Grafana that throw some pretty insane datasets at uPlot - like 2,000 series. since uPlot always creates one dom hover point per series, this now translates to 2,000 dom elements updated on every mouse move.

even after we disable the massive/useless live legend (also in the dom), we still have obvious super badness. 10s of continuous mousemoves results in only 570ms of browser idle time, with heavy UI lag and cpu burn:

image

a new cursor.points.one: true option switches uPlot to only create a single hover point which is reused across all series and only shows up for the closest hovered series and data index. how does it do that? it relies on the series focus functionality that uses proximity setting, so you also need to set cursor.focus.prox >= 0, and if you dont want series dimming, also focus.alpha: 1.

additionally, the first listed commit disables formatting values with a static or disabled legend.

with these settings and legend disabled we now have 8935ms of browser idle time and no perceivable UI lag :tada:

image
leeoniya commented 2 months ago

on the Grafana side...

original:

image

cursor.points.one: true:

image

cursor.points.one: true + newVizTooltips feature flag:

image