plotly / plotly.js

Open-source JavaScript charting library behind Plotly and Dash
https://plotly.com/javascript/
MIT License
17.14k stars 1.87k forks source link

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

Closed stereokai closed 5 months ago

stereokai commented 2 years ago

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!

alexcjohnson commented 2 years ago

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)

archmoj commented 2 years ago

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 commented 2 years ago

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.

stereokai commented 2 years ago

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

archmoj commented 2 years ago

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.

stereokai commented 2 years ago

@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?

archmoj commented 2 years ago

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 commented 2 years ago

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

stereokai commented 2 years ago

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);
  }
archmoj commented 2 years ago

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,
};
stereokai commented 2 years ago

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
alexcjohnson commented 2 years ago

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.

genseirin commented 1 year ago

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

gvwilson commented 5 months ago

Hi - we are trying to tidy up the stale issues and PRs in Plotly's public repositories so that we can focus on things that are still important to our community. Since this one has been sitting for a while, I'm going to close it; if it is still a concern, please add a comment letting us know what recent version of our software you've checked it with so that I can reopen it and add it to our backlog. Alternatively, if it's a request for tech support, please post in our community forum. Thank you - @gvwilson