ui: resource tree: improve performance on initial update

When we insert nodes into the tree, we use 'insertBefore' of extjs'
NodeInterface. When the node is inside a TreeStore, it calls
'registerNode' to handle some events and accounting. Sadly it does so
not only for the inserted node, but also for the node in which is
inserted too and that calls 'registerNode' again for all of its
children.

So inserting a large number of guests under node this way has (at least)
O(n^2) calls to registerNode.

To workaround this, create the first tree node structure outside the
TreeStore and add it at the end. Further insertions are more likely to
only come in small numbers. (Still have to look into if we can avoid
that behavior there too)

This improves the time spend in 'registerNode' (in my ~10000 guests test
setup) from 4,081.6 ms to about 2.7ms.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
Link: https://lore.proxmox.com/20250905120627.2585826-4-d.csapak@proxmox.com
This commit is contained in:
Dominik Csapak 2025-09-05 13:52:01 +02:00 committed by Thomas Lamprecht
parent 525738c070
commit d2660fc7a4

View file

@ -328,10 +328,22 @@ Ext.define('PVE.tree.ResourceTree', {
return node;
};
let firstUpdate = true;
let updateTree = function () {
store.suspendEvents();
let rootnode = me.store.getRootNode();
let rootnode;
if (firstUpdate) {
rootnode = Ext.create('Ext.data.TreeModel', {
expanded: true,
id: 'root',
text: gettext('Datacenter'),
iconCls: 'fa fa-server',
});
} else {
rootnode = me.store.getRootNode();
}
// remember selected node (and all parents)
let sm = me.getSelectionModel();
let lastsel = sm.getSelection()[0];
@ -451,6 +463,11 @@ Ext.define('PVE.tree.ResourceTree', {
me.selectById(lastsel.data.id);
}
if (firstUpdate) {
me.store.setRoot(rootnode);
firstUpdate = false;
}
// on first tree load set the selection from the stateful provider
if (!pdata.updateCount) {
rootnode.expand();