plotly.js icon indicating copy to clipboard operation
plotly.js copied to clipboard

What can I do to improve the performance? (already using scattergl)

Open stereokai opened this issue 2 years ago • 12 comments

Please see: http://www.stereokai.com/multi-charts-comparison/#plotly The code can be found here: https://github.com/stereokai/multi-charts-comparison/blob/publish/renderers/Plotly/Plotly.js#L22-77

Problem: Janky and slow graphical performance

Question: What can I improve in my code to squeeze more FPS from Plotly.js?

PS. This is my first time using plotly.js, and I have to say, the API is great, and despite struggling with the documentation, this implementation took me relatively little time compared to all other charting libraries I tried!

stereokai avatar Jun 15 '22 14:06 stereokai

Glad you like it @stereokai! The one usage technique I've seen to sometimes help with data like this is explicitly downsampling based on the ranges given by relayout events - but that introduces its own delay so is not always a win. The other thing I'll note is zooming / panning by dragging the axis itself (note that dragging near the ends of the axis will zoom, dragging near the middle will pan) or by choosing "pan" from the toolbar at the top is much smoother than dragging in the rangeslider because we do it with a simple rescale until you mouse up. That's another thing we could fix with more attention to the rangeslider (see https://github.com/plotly/plotly.js/issues/6231#issuecomment-1157065970)

alexcjohnson avatar Jun 15 '22 23:06 alexcjohnson

Curious to know if using a partial package like plotly.js-gl2d-dist-min that includes only gl2d traces (or even better a custom bundle that only include scattergl), could help improve the load time?

archmoj avatar Jun 16 '22 00:06 archmoj

On another note, considering your use case of plotting time-series setting layout.hovermode = 'x' (instead of the closest v2 default) can give you faster hover interactions.

archmoj avatar Jun 16 '22 00:06 archmoj

Guys thanks so much for your time.

@alexcjohnson

explicitly downsampling based on the ranges given by relayout events

  1. Is there any example of this somewhere?
  2. Doesn't plotly apply any downsampling to the data/pixels rendered internally?
  3. Any recommended downsampling algorithms or existing JS libraries?

zooming / panning by dragging the axis itself

  1. That's a problem from my point of view because it limits user interaction in some ways, but either way, even panning and mousewheel zoom on the charts is laggy
  2. Irregardless - does the same apply to zooming / panning on the chart itself vs the axis?

@archmoj

  1. Curious to know if using a partial package like plotly.js-gl2d-dist-min that includes only gl2d traces (or even better a custom bundle that only include scattergl), could help improve the load time?

Will definitely give it a chance and report back

On another note, considering your use case of plotting time-series setting layout.hovermode = 'x' (instead of the closest v2 default) can give you faster hover interactions.

I am currently using layout.annotations: false, as well as hoverinfo: "none" on each trace. Is there a difference?

Is there anything else in my configuration that I can improve to improve the graphical performance? You can find my current plotly.js configuration here: https://github.com/stereokai/multi-charts-comparison/blob/publish/renderers/Plotly/plotly.config.js

Million thanks

stereokai avatar Jun 16 '22 00:06 stereokai

Is there anything else in my configuration that I can improve to improve the graphical performance? You can find my current plotly.js configuration here: https://github.com/stereokai/multi-charts-comparison/blob/publish/renderers/Plotly/plotly.config.js

Million thanks

Instead of blocks like this, I suggest you use template. Here is a demo.

archmoj avatar Jun 16 '22 00:06 archmoj

@archmoj Thanks for this tip! Will definitely get rid of that uglyness. How does it affect performance internally?

Also any chance you can give this question a moment?

On another note, considering your use case of plotting time-series setting layout.hovermode = 'x' (instead of the closest v2 default) can give you faster hover interactions.

I am currently using layout.annotations: false, as well as hoverinfo: "none" on each trace. Is there a difference?

stereokai avatar Jun 16 '22 07:06 stereokai

On another note, considering your use case of plotting time-series setting layout.hovermode = 'x' (instead of the closest v2 default) can give you faster hover interactions.

I am currently using layout.annotations: false, as well as hoverinfo: "none" on each trace. Is there a difference?

I think some extra steps might be avoided using hovermode: fasle compared to hoverinfo: 'none'. Again if you need hover interactions, for your case hovermode: 'x' may be a good option.

archmoj avatar Jun 16 '22 13:06 archmoj

On another note - you could set config.plotGlPixelRatio: 1 for fast rendering.

archmoj avatar Jun 16 '22 13:06 archmoj

On another note - you could set config.plotGlPixelRatio: 1 for fast rendering.

@archmoj I could find only a few examples online, I understand it should go on the data object, like this?

data.config = data.config || {};
  data.config.plotGlPixelRatio = 1;
  if (!hasInitialized) {
    Plotly.newPlot(chart, data, layout, config.options);
    initEvents();
  } else {
    Plotly.react(chart, data, layout, config.options);
  }

stereokai avatar Jun 16 '22 13:06 stereokai

On another note - you could set config.plotGlPixelRatio: 1 for fast rendering.

@archmoj I could find only a few examples online, I understand it should go on the data object, like this?

data.config = data.config || {};
  data.config.plotGlPixelRatio = 1;
  if (!hasInitialized) {
    Plotly.newPlot(chart, data, layout, config.options);
    initEvents();
  } else {
    Plotly.react(chart, data, layout, config.options);
  }

No. You you should add it here.

export const options = {
  plotGlPixelRatio: 1,
  scrollZoom: true,
  responsive: true,
};

archmoj avatar Jun 16 '22 13:06 archmoj

Thanks. This example here is misleading: https://codepen.io/MojtabaSamimi/pen/rNWjBoo

layout.hovermode: false didn't cause any visible performance improvement.

I also gave plotGlPixelRatio: 1 a try. It makes for a minor graphics performance improvement but at a significant cost in visual fidelity - the charts are now very blurry: Before: image

After: image

stereokai avatar Jun 16 '22 14:06 stereokai

Re: downsampling: ironically we DO downsample, in a way that should have almost zero visual impact, when drawing SVG line traces. But I don't believe we do for gl2d because in general the downsampling operation there is slower in our experience than just drawing all the points. These days I spend most of my own time in Python so I'm not sure about JS libraries to do this, but specifically for time series https://github.com/predict-idlab/plotly-resampler (not made by Plotly, but targeting Plotly charts) does a very good job and may have some good inspiration for you.

Re: zoom / pan: actually my statement about rangeslider vs interactions on the plot itself may only be relevant to SVG traces. The technique we use with SVG to do a fast rescaling while the mouse is down, then redraw on mouse up, can't be done in webgl because we need to make one large canvas that covers the entire plot area (so as to not use too many webgl contexts) and in the general case there may be subplots that aren't being moved while some of them are.

alexcjohnson avatar Jun 16 '22 19:06 alexcjohnson

Does anybody know if there has been a development regarding a library like Plotly Resampler for Plotly.js?

genseirin avatar Jun 26 '23 11:06 genseirin