svelecte icon indicating copy to clipboard operation
svelecte copied to clipboard

Performance issues in v5 when opening with many options in spite of virtual list being enabled

Open CHamalainen opened this issue 8 months ago • 6 comments

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 text and value key/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

CHamalainen avatar Apr 10 '25 08:04 CHamalainen

Interesting 🤔 will look into it

mskocik avatar Apr 10 '25 08:04 mskocik

@mskocik Thank you for your quick reply 🙏 let me know if you need anything else, or if I can help out in any way!

CHamalainen avatar Apr 10 '25 08:04 CHamalainen

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 avatar May 27 '25 15:05 jkorrek

@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

mskocik avatar May 27 '25 18:05 mskocik

About 35000 & the options were also using a data object in addition to "just" id and text.

jkorrek avatar May 28 '25 05:05 jkorrek

@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 }; }),
];

CHamalainen avatar Jun 05 '25 11:06 CHamalainen

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 avatar Jul 28 '25 20:07 tonygoldcrest

@tonygoldcrest thanks, will look into it today

mskocik avatar Jul 29 '25 04:07 mskocik