Tree: Performance is bad when you have a large number of children
Describe the bug
When you start to load more then 100/200 children into a tree, then the performance opening the tree is really bad, the page just hangs.
I'm pretty sure this can be easily resolved by just adding the virtual scrolling component to the tree where it renders the children.
Here is a demo: https://stackblitz.com/edit/wcrnhu just try and open the documents tree
Reproducer
https://stackblitz.com/edit/wcrnhu
PrimeVue version
4.0.4
Vue version
4.x
Language
TypeScript
Build / Runtime
Vite
Browser(s)
No response
Steps to reproduce the behavior
Open the documents tree and wait for it to eventually load
Expected behavior
Open the documents tree and have it open instantly when there are more than 1000 objects in the data set.
Tagging @tugcekucukoglu please can you look into this? (I would try but seems master is broken for primevue as I can't run the dev server locally)
+1
We have the same issue and also wanted to use the filtering which is also painfully slow.
In my opinion a Tree should be able to handle a lot of data. Sadly I see more issues for components that do not work well with heavy datasets but are expected to like DataTable and TreeSelect. Could they be related?
Is the problem rendering nodes or executing some heavy method for each node?
Have you considered using a DataTable for displaying the rows and only use the Tree to navigate the hierarchy?
Nope, a DataTable isn't what we're after since we just have a single field to display.
Well, you can always use a single list instead, wrapped within a virtual scroller. The problem otherwise is that, with multiple lists under each parent node with their own scrollbars it might be a bit difficult to navigate, don't you think? And if you're going to push the height to the max so as to remove the scrollbars then there'd be no point in using the virtual scroller anyway, taking us back to square one. Else what do you suggest?
Here's the code used to iterate with children btw. It's a plain iterator and I'm not sure how to further optimize it:
<ul v-if="hasChildren && expanded" :class="cx('nodeChildren')" role="group" v-bind="ptm('nodeChildren')">
<TreeNode
v-for="childNode of node.children"
:key="childNode.key"
:node="childNode"
:templates="templates"
:level="level + 1"
:loadingMode="loadingMode"
:expandedKeys="expandedKeys"
@node-toggle="onChildNodeToggle"
@node-click="onChildNodeClick"
:selectionMode="selectionMode"
:selectionKeys="selectionKeys"
@checkbox-change="propagateUp"
:unstyled="unstyled"
:pt="pt"
/>
</ul>
Anyway, the upcoming Vue 3.5 will come with significant performance gains out of the box so, hopefully, that'll fix it out of the box.
Yeah I mean this is what I had:
<VirtualScroller :items="node.children" showLoader :itemSize="17" :numToleratedItems="20" style="height: 200px">
<template #item="{ item }">
<TreeNode
:key="item.key"
:node="item"
:templates="templates"
:level="level + 1"
:loadingMode="loadingMode"
:expandedKeys="expandedKeys"
@node-toggle="onChildNodeToggle"
@node-click="onChildNodeClick"
:selectionMode="selectionMode"
:selectionKeys="selectionKeys"
@checkbox-change="propagateUp"
:unstyled="unstyled"
:pt="pt"
/>
</template>
</VirtualScroller>
But as you say, it creates a scrollbar for every group which is slightly annoying. But I feel like there could still be some optimisation done by utilising the concept of a virtual scroller, i.e. knowing what is visible and only rendering those items.
Our use case is that we have it in a dialog so it don't just fill the entire page up, it's confined to a space and there's a scrollbar.
Related: https://github.com/primefaces/primevue/issues/5396
Profiling shows that a huge amount of time is being spent (wasted?) in setAllNodeTabIndexes when adding a large amount of children to a TreeNode.
Tagging @tugcekucukoglu again to see if we can get this worked on?
We tried to implement the TreeSelect component, but because we have large datasets (1000+ items with 3 levels is no exception for us) this is unworkable now. Loading times exceed 10 seconds, which is unacceptable for our clients.
Adding some virtual scrolling / lazy-loading functionality would certainly help I think, if the base performance for such large datasets isn't getting any better than this.
Hi @agersant @tugcekucukoglu we use primevue with Tree.vue and... same issue for us. But if i remove setAllNodesTabIndexes from TreeNode.vue i can continue to use keyboard for accessibility. And... Performance are nice after that ! Do you think this method is really usefull ? I may be missing something
+1 to this @tugcekucukoglu could we get some virtual scrolling or options to disable the problematic setAllNodesTabIndexes function
Still very slow for us even without setAllNodesTabIndexes. 1k+ nodes is taking over 7/8 seconds to load. Unable to use component
Same also very slow for us with around 100 items
@tugcekucukoglu do you know anything about a timeline of this issue? we want to use the tree from primevue as our main tree-component in many cases, but the performance is very bad. we just have 1 root element with 3 children and already a lagging/slow behaviour when open and close the tree.
Experiencing this issue too
Any update on this?