How do we increase RadTreeView performance?

1 Answer 51 Views
Treeview
Phil Lindquist
Top achievements
Rank 1
Phil Lindquist asked on 01 Mar 2022, 09:19 PM

We use Telerik UI for Winforms extensively in our Windows application.  We have migrated almost all of our UI to use Telerik UI for Winforms but we were using a 2014 release of Telerik.  Last month we updated to the latest (Q1 2022) Telerik UI for Winforms and began converting the last 3 major tree controls in our UI to use the RadTreeView.  The biggest of these tree controls can have a lot of nodes.  Some of our customers will exceed 750000 nodes in their installations.

We have found that when sorting is enabled, especially our custom sort which is necessary for our implementation, the tree control takes a VERY long time to load and also a very long time to repopulate when a leaf node with its children is removed and then re-added.  Of note when we remove/re-add a leaf node is that if I put a breakpoint into our NodeComparer implementation I see that many nodes from all over the tree are being compared.  The comparisons include nodes that are at the root of the tree and were not affected since the node(s) removed were 4 or 5 levels down and restricted in scope to just one sub-collection.  I am very surprised that the RadTreeView re-sorts ALL of the tree nodes rather than just the nodes in the affected collection?

Are there ways to restrict sorting to just the collection affected by the addition/removal of a node?

Phil Lindquist
Top achievements
Rank 1
commented on 02 Mar 2022, 01:45 AM

Out of curiosity I disabled all sorting on the primary tree control that we are converting to RadTreeView.  In spite of removing the sorting, adding nodes to this tree is still really slow.

A common action in our software is to "regenerate" a group of nodes representing devices on the network.  In this scenario a number of nodes are removed and then a new set of nodes are added back to the tree based on newly acquired data.

I found that if I regenerated a network (containing devices, object groups and objects) then adding 693 "object" nodes into 15 "group" nodes below just one "device" node took 119,651,964 ticks!  If I added a call to Nodes.DeferRefresh() (see code below) then the time taken dropped to 660,000-700,000 ticks.  That's a 170x or better improvement.  The problem is, I don't actually know what side effects I'm going to get from DeferRefresh().

 

 


                            if (objectNode != null)
                            {
                                if (objectNode.ObjectType != BACstac_Object_Type.Device)
                                {
                                    #region Find or Create Group Node
                                    Type groupType = null;
                                    if (getGroupType(VendorID, ModelName, FirmwareRevision, objectRow.ObjectType, objectRow.ObjectInstanceID, out groupType, out errorMessage) == false)
                                    {
                                        //TODO: This is a problem
                                        OutputWindow.addMessage(OutputWindow._OutputType.Error, @"Did not find a group type for " + objectRow.ObjectType.ToString(), @"Network Manager");
                                        continue;
                                    }
                                    
                                    BACnetObjectGroupNode groupNode = null;
                                    if (m_objectGroups.TryGetValue(groupType, out groupNode) == false)
                                    {
                                        System.Reflection.ConstructorInfo info = groupType.GetConstructor(paramTypesArray);
                                        groupNode = info.Invoke(parametersArray) as BACnetObjectGroupNode;
                                        m_objectGroups.Add(groupType, groupNode);

                                        Nodes.DeferRefresh();
                                        Nodes.Add(groupNode);
                                    }

                                    groupNode.Nodes.DeferRefresh();
                                    groupNode.Nodes.Add(objectNode);
                                    #endregion
                                }

                                newObjectList.Add(objectNode);
                            }

1 Answer, 1 is accepted

Sort by
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 03 Mar 2022, 09:57 AM
Hello, Phil,

To improve performance in data loading and other long running operations use the RadTreeView's BeginUpdate and EndUpdate methods. Place BeginUpdate and EndUpdate just before and after blocks of code that add, remove or reorder large numbers of nodes. However, to be honest, 750 000 nodes is a very big number of nodes for RadTreeView. The possible solution that I can suggest to achieve as good as possible performance is to use the load on demand functionality. This helps RadTreeView to reduce performance and memory costs incurred when all nodes are loaded at once. To benefit from this feature, you just need to handle the NodesNeeded event where you can fill the parent nodes with sub-nodes. 

Please refer to the following help article: https://docs.telerik.com/devtools/winforms/controls/treeview/data-binding/load-on-demand 

Feel free to have a look at our Demo application >> TreeView >> Populate with Data >> Load on Demand example. To access the Live Demo simply click on the Windows Start button and type WinForms Demo.

I hope this information helps. If you need any further assistance please don't hesitate to contact me. 

Regards,
Dess | Tech Support Engineer, Principal
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Tags
Treeview
Asked by
Phil Lindquist
Top achievements
Rank 1
Answers by
Dess | Tech Support Engineer, Principal
Telerik team
Share this question
or