Performance issues in v5 when opening with many options in spite of virtual list being enabled
Hello, and thanks for a great package.
We are updating a project relying heavily on Svelecte to version 5, and suddenly run into performance issues with opening the select when having a lot of options, in spite of enabling the virtual list. In version 4 the performance is great with the same number of options.
Step to reproduce:
- Initialize a Svelecte component with Virtual List enabled and 8000+ options supplied
- The options are objects containing only the
textandvaluekey/value pairs.
Results:
- It takes around 3 seconds for the options to be rendered after the first click, while in version 4 it is instant.
- Increasing the options count increases the time it takes to be rendered, while reducing the options count reduces the rendering time
- Subsequent clicks are rendered instantly
Videos:
Svelecte version 5 https://github.com/user-attachments/assets/d912fa2c-01ea-4a99-85cc-2d67c572f8c7
Svelecte version 4 https://github.com/user-attachments/assets/1c69cc3e-8579-4447-8939-d57b17862b02
Interesting 🤔 will look into it
@mskocik Thank you for your quick reply 🙏 let me know if you need anything else, or if I can help out in any way!
Bit of a shot in the dark, but this somewhat sounds like a problem I ran into.
The bad performance in my case had actually nothing to do with svelecte but with using the $state rune for the options passed to svelecte. Svelte sets up deep reactivity, which gets slower, the larger the options list becomes.
Switching to $state.raw to bypass deep reactivity solved the problem. You need to keep in mind, that you have to reassign the options list when using $state.raw, but that was not a problem for me.
This might be worth mentioning in the docs as a general performance hint.
@jkorrek how big option list are you talking about?
But I can see there is definitely a lag with long list. https://svelte.dev/playground/db6383809680434dad68616fff27ec31?version=5.33.4
About 35000 & the options were also using a data object in addition to "just" id and text.
@jkorrek Thank you for chiming in.
I am not tracking the options provided through the $state rune, but as a prop declared with the $props rune. It get's passed through a couple of components before hitting Svelecte.
At the top level it is initialised without reactivity in mind, just as the following
const options = [
{ value: null, text: '- Select an option -' },
...Object.entries($myOptionsStore).map(([optionName]) => { return { value: optionName, text: optionName }; }),
];
Hi! I think I've identified a bug related to virtualList=true that causes the component to lag when the dropdown is first opened.
The issue seems to be in this line: https://github.com/mskocik/svelecte/blob/08a3e736ebe2b8d5bae7e1e32bef13e748592b83/src/lib/Svelecte.svelte#L1600
On the initial open, ref_container_scroll === null, which causes the condition to evaluate as false. As a result, it falls back to rendering all 8000+ items in the DOM - even if just briefly - which leads to the initial lag.
Removing this extra condition (&& ref_container_scroll) seems to resolve the issue.
Unfortunately, I can't submit a PR at the moment. @mskocik would you be able to take a look and possibly fix it? Thanks!
@tonygoldcrest thanks, will look into it today