How can I improve the perfomance updating data working with many plots and tabs?

I am using bokeh as a Server Application, and I hope someone has some suggestions for my issue.

I have 4-10 tabs with 2-10 plots each one. I need to draw some lines (profiles) and other scatter points in all the plots of all tabs when some samples are selected. If I update these profiles just in the current tab everything works smoothly and without any problem. But when I update all the profiles in all the tabs, the app takes a long time to update the samples (5-10 seconds).

Solutions I have discarded:

  • Dask. The algorythm takes just 1-2 seconds in creatin the new data, so the problem happens when the data is sent to the front-end. Also, Dask Dataframe have some overhead and I believe they are meant to work with a bigger amount of data
  • Datashader. The user must be able to click on all the points all the time, they are around 3000 samples in each plot. So I cannot use this approach either
  • Update the data in two steps. I can update just one tab and a few seconds later the rest of tabs. The current tab is updated well, but when I update the data of the rest of the tabs the app freezes, so this is not a good idea. I asked time ago for a callback that is triggered when everything is rendered, however, I am afraid I will have the same problem as with the timeout I tested.
  • Using patch instead of updating the whole dataframe takes the same amount of time. I believe this is because it takes a lot to build the patches structure.

Actually, I don’t know where the bottle neck is and how to check it. It has to be when transfering the data to the front-end or when bokeh is redrawing the glyph with new data. How can I check that?

Is there a better way to update in two steps and keep the app interactivity working? Is there a better way to improve the performance of this data updates?

Can Web Workers help in with this process in some way?

I made some analysis when I press some sample to draw the profiles

Is there a code that you could share that exhibits the behavior?
Can you create a new performance profile, save it, and send the resulting file? It’s the fifth button at the Performance tab toolbar.

1 Like

Thanks for your interest. I uploaded the profile here. It’ll be available in the link for one week.

The source code can be kind of cumbersome because it is inside an app here. Basically, I update the CDS of one multiline glyph, a circle glyph (around 40 points each) and a couple of asterisk glyphs (just one sample for them).

You can even download and install the app if you want to give some advice. The version v1.1.0 should work in all operating systems

From the profile, it seems that the vast majority of time is taken by WebGL. Have you tried disabling it? I see that you specify output_backend=OUTPUT_BACKEND, where OUTPUT_BACKEND = 'webgl'. There’s also backend=webgl query parameter but I have no idea whether it’s used by something.

1 Like

I got some data from https://www.nodc.noaa.gov/woce/woce_v3/wocedata_1/whp/data/onetime/atlantic/a25/index.htm just to test it. The first test was with the WebGL backend, and it was indeed slow. The second test was done with OUTPUT_BACKEND = 'canvas', and it was 2-3 times faster, so the comment in the source file about it being switched to webgl automatically is definitely incorrect. Also, now I’m pretty sure that the backend=webgl query parameter specified in main_renderer.js is not used - it’s probably better to remove it.

I’ll try understand what takes the most time with the canvas backend now.

1 Like

Seems like it is just what it is - it’s just the rendering of 28 plots (well, with the data that I’ve found) that makes it slow. And the app does change all of the plots if I select something within just one.

If you’re still not content with the performance after switching the output backend to canvas, there’s another way to solve it. You can create your own tab component (that may or may not be Bokeh-aware) that renders just the required plots, and when you switch to a new tab, the old plots will be removed and the new ones will be rendered. It will make switching between tabs a bit slower but it will make any operation on any plot much faster. Well, unless you have just 1 tab with 28 plots on it of course.

1 Like

Thanks for devoting your time to analyse the app !!

I did not realise that output_backend could affect the performance so much because I really did not notice it in my computer. I have just tested it in a slower computer and actually the performance is improved as you say. Let’s see if the final users do not complain after the change.

I have read as well some webgl performance issues in the GitHub page of Bokeh. I hope they find someone to enhance that part.

I may try to implement your suggestion of drawing less plots at once, if I have time. Thank you. I do not know if I can even use the tabs component of bokeh and just update the panels directly. I would need to check if there is some trigger there in order to replot the tab content.

I will let you know if there is some new news