leeoniya/uPlot

remove redundant lineTo commands by rendering data as columns

1wheel opened this issue · 5 comments

hey @1wheel , this looks pretty sweet. i actually saw this technique buried in some chart lib's docs with a bunch of caveats just a few days ago. i'm trying to find where i saw it and it's driving me nuts!

something similar here: https://www.amcharts.com/docs/v4/concepts/performance/#Simplifying_paths

thanks for the demo! unless you want to take a stab at this impl in uPlot, i'm going to focus on some of the other todos first and revisit this later. you know what they say about premature optimization 🤣

EDIT: ah, here we go [1], but it's not really talking about line charts, just column and bar chart rects all being 1px wide. tangentially related.

[1] https://www.highcharts.com/docs/advanced-chart-features/boost-module

@1wheel i did a basic test of this strategy in another branch [1] and it does indeed shave about 50% off the render time. toggling a series on/off (which is a full rescale/redraw) went from ~23ms -> ~12ms. i'm using fillRect() calls at the pixel boundaries rather than lineTo() at +0.5 offsets. fillRect handles 1x1 sizes more naturally, too.

i don't have any gap-filling logic there yet, so at higher zoom levels it's just dots.

[1] https://github.com/leeoniya/uPlot/tree/reduce-lineTo

a simplified variant of this has been implemented. thanks for the suggestion & PoC! 💯

interestingly, this optimization does not save the same 12ms off the cold start render time - that only drops by ~2ms (out of ~45ms).

btw, i think i nabbed the cold-start issue in 9d71ac9. i'm guessing it was a V8 de-opt due to some stuff ending up as NaNs as a result of declared but undefined vars at the start of the drawing loop.

oh interesting!