I have a tree that I am generating that can possibly generate 1000's of nodes. Each node has an icon and text.
In situation where I have a couple of hundred, no problem. When I get into the 1000's, I get 'Out Of Memory' errors. If I take out the icons, no issue.
Not sure where to start with this, but I have an imagelist with 16x16 icons...png's. (Very small)
Here is an example of how I am generating certain levels of the tree:
UltraTreeNode worknode = null;
public void GenerateDash(UltraTree tv)
{
worknode = tv.GetNodeByKey(SQLReader.GetString(21) + SQLReader.GetInt32(24));if (worknode == null){if (sid) worknode = tv.Nodes[SQLReader.GetInt32(24) + "mc"].Nodes.Add(SQLReader.GetString(21) + SQLReader.GetInt32(24), SQLReader.GetString(21)); else worknode = tv.Nodes["me"].Nodes[SQLReader.GetInt32(24) + "emp"].Nodes[SQLReader.GetInt32(24) + "mc"].Nodes.Add(SQLReader.GetString(21) + SQLReader.GetInt32(24), SQLReader.GetString(21));worknode.LeftImages.Add(tv.ImageList.Images[12]); }if (tv.GetNodeByKey(SQLReader.GetString(21) + SQLReader.GetInt32(24) + SQLReader.GetString(22)) == null) { worknode = worknode.Nodes.Add(SQLReader.GetString(21) + SQLReader.GetInt32(24) + SQLReader.GetString(22), SQLReader.GetString(22)); worknode.LeftImages.Add(tv.ImageList.Images[35]);}else worknode = tv.GetNodeByKey(SQLReader.GetString(21) + SQLReader.GetInt32(24) + SQLReader.GetString(22));
}
Before this I had a standard .net tree which generated the same amount of nodes with the icon with no issue.
Thanks.
Hi,
What version of the tree are you using?
You might want to try specifying an index to the LeftImages collection instead of an image.
For example, you could do this:
worknode.LeftImages.Add(12);
This will work the same as what you have now, assuming that you have set the tree's ImageList property to your tv.ImageList. This also assumes that you are only using one ImageList for all of your images.
If that does not help, then we would need to look into this further. How many different images do you have? I assume you don't have thousands of images, but you are probably re-using the same set of images for multiple nodes.
If you could provide a small sample project demonstrating the issue, we would be happy to take a look.
I stepped the imagelist itself from 32 to 16 bit color depth. That and I changed out all of the png's to ico's. This resolved the out of memory issue. The silly thing is that after I changed all of the images to ico's, the ico's are twice the size of the png's. I just assumed they would be smaller. (2K instead of 1K).
I have to tell you, that while I did have an image list associated to the tree, I changed worknode.LeftImages.Add(tv.ImageList.Images[12]) to your suggestion and it cut the time it takes the tree to generate in half. I have read your post regarding memory considerations for the ultragrid, is there one for the tree? We use a lot of the trees.
There are 34 images in the list, though only half are being used with any real frequency. My test data is returning over 20K nodes in total.
melegant said:I have to tell you, that while I did have an image list associated to the tree, I changed worknode.LeftImages.Add(tv.ImageList.Images[12]) to your suggestion and it cut the time it takes the tree to generate in half.
That's interesting. I suspected that that might be the case, because when you specify an image, the tree cannot compare that image to any other image. So if you use tv.ImageList.Images[12] on two different nodes, the tree has no way of knowing that they are the same image. When you simply use the number 12 as an indexer into the ImageList, it knows the images are the same, so it can optimize things and re-use the same image.
melegant said: I have read your post regarding memory considerations for the ultragrid, is there one for the tree? We use a lot of the trees.
I don't believe there is any guide specific to the tree, but a lot of the same concepts from the WinGrid Performance Guide apply to the tree or other controls, too. The section on re-using Appearances, for example, applies to all of the controls. It does not apply to LeftImages and RightImages directly, since these are not Appearances, but re-using the images by indexing into the ImageList is essentially the same thing.
Is the current level of performance while using the indexes acceptable?
If not, then are you certain that the LeftImages is causing the major part of the performance issue? If you turn off the LeftImages entirely, is the performance acceptable at that point?
If that is the case, then there might be another potential solution using a DrawFilter. But 'm not sure if it will work. Try setting every node to the same image and see if that improves the performance. If it does, then what you could do is use the same image for every node and then use a DrawFilter to change the image. The advantage of this is that you only have to draw the images that are actually visible on the screen.
If assigning the same image to every node does not help, then you could still probably make this much faster by using a CreationFilter to add the ImageUIElement into the nodes yourself. Once again, this only has to operate on visible nodes, so it will be very fast and efficient. And I can help point you in the right direction in terms of coding the CreationFilter.
Still another option is that we could try to look into this and find out if the tree itself could be optimized to make this faster. In order to do that, we would need you to post a small sample project demonstrating the problem.
The GetNodeByKey method is probably pretty expensive, too, by the way. This method has to loop through every node in the tree until it finds one with the correct key.
Of course, that won't cause an OutOfMemoryException, but it could affect performance if you are calling this method a lot.
Hello,
I have created a support case for you CAS-47241-GGDSXY, so you can send the sample in private and I will investigate it.
Thank you.
Sincerely,DimiDeveloper Support EngineerInfragistics, Inc.
Applying the changes you suggested has resolved the issue and things are MUCH faster now.
Though, I would like for you guys to take a look at an example method of how we are populating the tree but I would rather not post it here. Is there way I can email it? Basically, we are using a single instance of a node to do all of the building. We follow this same basic format for all of our tree construction.
worknode = tv.GetNodeByKey(xyz);
if(worknode != null)
worknode = worknode.add(some stuff);
)
else
worknode = worknode = tv.nodes.add(etc);
worknode.Tag = xyz;
worknode.LeftImages.Add(1);
worknode.DataKey = xyz;
worknode.Nodes.add(next database item)