dash-core-components icon indicating copy to clipboard operation
dash-core-components copied to clipboard

Loading dropdown component with many items is slow

Open grst opened this issue 6 years ago • 16 comments

Similar to the issue described in #103, I am having trouble with the speed of very long dropdown lists (40k+ items). However, in my case it's not the speed of searching the dropdown list (which has been solved in #103), it's rather the time until the component is loaded dynamically.

Network issues should not be at play here, as everything is running locally.

Note the time between choosing to display the dropdown menu and the time until it actually shows up: peek 2019-01-20 16-52 (List with 100k items)

Minimal working example

minimal working example is here as a gist.

Dash versions

>conda env export | grep dash
- dash=0.35.1=py_0
- dash-core-components=0.42.0=py_0
- dash-html-components=0.13.4=py_0
- dash-renderer=0.16.1=py_0
- dash-table=3.1.11=py_0
- dash-bootstrap-components==0.3.0

grst avatar Jan 20 '19 16:01 grst

Running this locally, the network call takes ~400ms and the dropdown rendering ~8.5 seconds with the 100k items example above.

Most if not all the initialization time seems to be linked to fast filter options; you are probably hitting the same limit as was mentioned here.

Investigating the filter to get a feel for what is going on here.

Marc-Andre-Rivet avatar Jan 22 '19 13:01 Marc-Andre-Rivet

Investigation results

So.. we are using react-virtualized-select for the dropdown rendering and react-select-fast-filter-options for the underlying search functionality. fast-filter is using js-search to index the available options.

js-search creates a index of all label substrings (as labels are tagged as the key to filter on), creating ~700k valid partial filter entries for this dataset, containing roughly 100M references to the original options -- allocating ~600MB of memory... explaining the ~8 seconds load/processing time

The cost of creating the index is linked to the number of entries n, the number of keys k, and the length of each key entry e. Number of entries per item is at worse e*(e+1)/2, giving an overall load time worse case is O(nkc^2).

Conclusion

There is no simple solution to this performance issue. Either we find a more efficient library to take care of the filtering or we implement our own.

Other, hybrid approaches may or may not be compatible with the react-virtualized-select component. A combination of lazy loading, caching / busting and debouncing could get us a long way. This related to https://github.com/plotly/dash-table/issues/250.

Marc-Andre-Rivet avatar Jan 22 '19 14:01 Marc-Andre-Rivet

How about TrieSearch? I racall it to work quite well...

But actually, I think a server-side solution would be the way to go, as already the transfer-time is non-negligible and could be a bottleneck when not running locally.

In R shiny, a server-side selectizeInput is implemented, and it works flawlessly for the same usecase.

grst avatar Jan 22 '19 18:01 grst

We actually had someone suggesting something similar (server-side updates to the dropdown options) here. Turns out the react-virtualized-select component does not behave well when its options are changed on the fly / while the dropdown is opened.

Thanks for the TrieSearch suggestion, will look into it.

Marc-Andre-Rivet avatar Jan 22 '19 20:01 Marc-Andre-Rivet

Moving this issue to the dash-core-components repo.

Marc-Andre-Rivet avatar Jan 22 '19 20:01 Marc-Andre-Rivet

Just wondering... is there an alternative by now? This issue is basically the only thing preventing me to switch from Shiny to dash...

grst avatar Sep 05 '19 18:09 grst

Also wondering if there is any update or alternative to this issue.

It wouldn't usually be a problem, but my team has a Dash app integrated into flask app by following this guide (the last chapter, using WSGI) and the issue is that the fast parts of the front end are being loaded instantly, while Dropdown menu along with some other components loads after about 15-20 seconds.

I have tried removing the dropdown menu and rendering only other components, and such layout loads instantly.

For reference, the list which should be displayed in a dropdown menu has 12907 items.

danchyy avatar Nov 18 '19 13:11 danchyy

Hi, I am also facing performance issue with updating a dropdown with ~10k items. Has anyone solved this issue?

anubhav-nd avatar Jan 14 '20 08:01 anubhav-nd

Same here, any solution?

LucaMarconato avatar Apr 13 '20 21:04 LucaMarconato

Have folks tried the "Dynamic Options" alternative mentioned in the Dropdown documentation? https://dash.plotly.com/dash-core-components/dropdown

This would be the recommended way forward when dealing with hundreds, thousands, or millions of options.

chriddyp avatar Apr 13 '20 21:04 chriddyp

Thank you for the blazing fast response! Unfortunately in my case I would need a dropdown, if no solution/workaround is possible I will switch, but letting the user both see the dropdown values and being able to search would be better.

LucaMarconato avatar Apr 13 '20 21:04 LucaMarconato

@LucaMarconato how many options are trying to display? And by "I need a dropdown", you mean that you need the user to be able to see every option that is available?

chriddyp avatar Apr 13 '20 22:04 chriddyp

I have approximately 1000 options. Long story short (for the other people reading this), I can avoid using the dropdown if it is a problem right now. For completeness in the rest of the comment I explain why in my scenario a dropdown would be, I think, preferable.

I am working with data that it is indexed using a string which is a concatenation of parameters. The best would be to use a better way to index the data but since the data is from other people and other tools have been built from the data using that indexing system, I prefer to just use adhere to their convention. What I am currently implementing is to use a integer index (for instance with a input widget) and when a number is selected I display the original string, the problem is that sometimes a person could be interested in just a subset of the data and so a integer number is not really a "key", and this ambiguity could be a bit confusing/time consuming when multiple people want to collaborate but are not working on slightly different set of items.

LucaMarconato avatar Apr 13 '20 22:04 LucaMarconato

Nice, @chriddyp! With the dynamic option available, feel free to close the issue from my side.

grst avatar Apr 14 '20 09:04 grst

I think the issue is not actually in the Plotly dash dropdown or DCC. The issue is with dropdown itself in html you can see many question in the internet like this which are not related Dash. The browser tries to load all the options in its memory so its taking time.

ravitejapavuluri avatar Mar 30 '22 03:03 ravitejapavuluri

Wanting to bump this issue because we're working with this same problem but would prefer to have the dropdown function as intended as much as possible rather than moving to a dynamic callback altogether, e.g. we want to see all of the options in the dropdown list rather than having to search-and-see.

JamesKunstle avatar May 26 '22 15:05 JamesKunstle