Robbe
Sun Sep 24 21:27:47 CDT 2006
Downloaded your sample from your blog. Ran it under
.NET 1.1 and .NET 2.0. You are correct, there is a
considerable difference in performance. I did adjust
your code to only use the .NET version rather than
your inherited class "just to be 100%" it wasn't you.
It wasn't.
I did get some improvement whenever I disabled
the tree prior to loading it or making a lot of node
changes and then enabling it again when done. I did
this before the beginupdate and after the endupdate stuff.
I worked with sets of 25 as well as lower volumes
around 18 - 20. Dropping down to around 10k nodes
seemed to provide acceptable performance for a typical
UI.
Still underperforms. You may want to get a hold
of Lutz's Reflector and compare the two System.Windows.Forms
assemblies and the TreeView class. You might be able to
identify the poor performing code and override it. Perhaps...
--
Robbe Morris - 2004-2006 Microsoft MVP C#
I've mapped the database to .NET class properties and methods to
implement an multi-layered object oriented environment for your
data access layer. Thus, you should rarely ever have to type the words
SqlCommand, SqlDataAdapter, or SqlConnection again.
http://www.eggheadcafe.com/articles/adonet_source_code_generator.asp
"kiwidude" <grant.drake@gmail.com> wrote in message
news:1158910650.194883.303070@i3g2000cwc.googlegroups.com...
> Hi Robbe,
>
> It is indeed my own implementation, but I'm not doing anything funky.
> All those performance figures above were from a completely clean test
> harness that just had that one override, no other changes from the
> TreeView defaults.
>
> I've written a blog entry about the problem:
>
http://www.kiwidude.com/blog/2006/09/net-20-treeview-performance-problem.html
>
> and put my sample code available for download from here:
>
http://www.kiwidude.com/dotnet/TreeViewTest.zip
>
> Regards,
> Grant.
>
> Robbe Morris [C# MVP] wrote:
>> Hmm. I downloaded my .net 1.1 sample and converted it to 2.0.
>>
>>
http://www.eggheadcafe.com/articles/treeview_databinding.asp
>>
>> It only runs 1 to 2 thousand nodes. Quite a bit smaller than
>> your sample. However, the speed is pretty darn quick
>> running your sample code.
>>
>> I see that you are overriding the standard event. Is
>> this your own overriden tree control implementation?
>>
>> --
>> Robbe Morris - 2004-2006 Microsoft MVP C#
>> Earn money publishing .NET articles at
>>
http://www.eggheadcafe.com
>>
>>
>>
>>
>> "kiwidude" <grant.drake@gmail.com> wrote in message
>> news:1158868254.411445.183090@h48g2000cwc.googlegroups.com...
>> > Here's the results of a very simple test harness I knocked up (chuck me
>> > an e-mail if you want the full code). It loads a tree with 1 x 25 x 25
>> > x 25 nodes (15,626 for those without a calculator). In the
>> > OnBeforeExpand method I do this (the if statements just wrap checkboxes
>> > in the test harness for the permutations):
>> >
>> > protected override void OnBeforeExpand(TreeViewCancelEventArgs e)
>> > {
>> > if (UseBeginUpdate) {
>> > BeginUpdate();
>> > }
>> > if (UpdateText) {
>> > for (int i = 0; i < e.Node.Nodes.Count; i++) {
>> > e.Node.Nodes[i].Text = "ChildUpdated" + i.ToString();
>> > }
>> > }
>> > if (UseBeginUpdate) {
>> > EndUpdate();
>> > }
>> > base.OnBeforeExpand();
>> > }
>> >
>> >
>> > The timing results are as follows for expanding a node (using
>> > QueryPerformance API for timings):
>> >
>> > Using .Net 1.1:
>> > 0.2 secs (with BeginUpdate and updating .Text)
>> > 0.2 secs (just updating .Text)
>> > 0.007 secs (with BeginUpdate)
>> >
>> > Using .Net 2.0
>> > 1.2 secs (with BeginUpdate and updating .Text)
>> > 30.6 secs (just updating .Text)
>> > 1.2 secs (with BeginUpdate)
>> >
>> > Setting Scrollable to false under .Net 2.0 (unusable but out of
>> > curiosity)
>> > 0.001 secs (just updating .Text)
>> >
>> >
>> > So in summary - you can see that .Net 2.0 for this size of tree is
>> > approximately six times slower than .Net 1.1 when using Begin/EndUpdate
>> > (and about 150 times slower just updating .Text without it which
>> > obviously is a bad thing to be doing). You can also see that just the
>> > call to BeginUpdate/EndUpdate alone still incurs a massive penalty even
>> > if you don't actually update anything.
>> >
>> > Waiting over a second while you expand a node that only has a couple of
>> > children is completely rubbish.
>> >
>> > Is anyone using a third party tree control that doesn't suck as badly
>> > under .Net 2.0, or has found some way of making this tree usable when
>> > your .Text contents need to be updated dynamically?
>> >
>> > Grant.
>> >
>> > kiwidude wrote:
>> >> Hi Robbe,
>> >>
>> >> The application is a code coverage GUI tool (NCoverExplorer).
>> >> Depending
>> >> on the "view" a user chooses (% visited, # seq pts unvisited etc) and
>> >> the node type the text is calculated appropriately.
>> >>
>> >> As for why so many nodes are being updated - that's exactly my point
>> >> in
>> >> that I do not actually update all that many nodes (just the immediate
>> >> children of the node being expanded which is usually in the 10-20 node
>> >> region). When I profile this under .Net 1.1 I see several orders of
>> >> magnitude less in the way of messages etc. However in .Net 2.0 it just
>> >> explodes in the amount of work going on underneath.
>> >>
>> >> In fact when I comment out the code actually doing the updating of
>> >> nodes and do nothing but BeginUpdate/EndUpdate in the OnBeforeExpand
>> >> method I still see the same poor performance.
>> >>
>> >> Regards,
>> >> Grant.
>> >>
>> >> Robbe Morris [C# MVP] wrote:
>> >> > I have not seen these types of performance issues. I know
>> >> > the tree loads a few thousand nodes rather quickly for me.
>> >> >
>> >> > I do a fair amount of work with hierarchies in research
>> >> > applications. So, I'm somewhat familiar with apps that
>> >> > do this sort of thing.
>> >> >
>> >> > Out of curiousity, are the percentages on each TreeNode
>> >> > a percentage within its siblings or are the percentages
>> >> > of themselves in conjunction with either their parents
>> >> > or their own sibling branches?
>> >> >
>> >> > Typically you'd expect it to be the percentages of
>> >> > siblings. In that case, there would only be 10 or 20
>> >> > siblings to update.
>> >> >
>> >> > I realize your existing code worked in .net 1.1 but
>> >> > could you shed some light on why you need to adjust
>> >> > so many nodes in the OnBeforeExpand event?
>> >> >
>> >> > --
>> >> > Robbe Morris - 2004-2006 Microsoft MVP C#
>> >> > Earn money publishing .NET articles at
>> >> >
http://www.eggheadcafe.com
>> >> >
>> >> >
>> >> >
>> >> >
>> >> > "kiwidude" <grant.drake@gmail.com> wrote in message
>> >> > news:1158787900.810912.31450@i42g2000cwa.googlegroups.com...
>> >> > > All,
>> >> > >
>> >> > > Microsoft appear to have changed the internal implementation of
>> >> > > the
>> >> > > TreeView control and the changes appear to be not for the better
>> >> > > as
>> >> > > far
>> >> > > as my application is concerned. Has anyone else had performance
>> >> > > issues
>> >> > > with it?
>> >> > >
>> >> > > The issue I have is that I need to change the .Text and
>> >> > > .ImageIndex
>> >> > > of
>> >> > > the nodes AFTER the tree has been populated. This is because the
>> >> > > tree
>> >> > > contains percentages etc based on the children of each node.
>> >> > >
>> >> > > In .Net 1.0/1.1 I had this finely tuned to do a "load on demand".
>> >> > > I
>> >> > > override OnBeforeExpand() so as you expand a node it updates the
>> >> > > text/imageindex of the children which works really well. The
>> >> > > number
>> >> > > of
>> >> > > node children is usually around the 10-20 mark but often only a
>> >> > > few,
>> >> > > so
>> >> > > very little processing involved this way. Performance is great
>> >> > > under
>> >> > > 1.1.
>> >> > >
>> >> > > However running exactly the same code under .Net 2.0 gives what
>> >> > > ranges
>> >> > > from "appalling" to just plain "dire" usability.
>> >> > >
>> >> > > The "improved" performance is gained by adding
>> >> > > BeginUpdate/EndUpdate
>> >> > > around the code which iterates through the child nodes updating
>> >> > > the
>> >> > > .Text. However the performance is still completely awful compared
>> >> > > to
>> >> > > .Net 1.1, and it comes down to the .EndUpdate method which is
>> >> > > chewing
>> >> > > up the time in it's calls to Control.SendMessage.
>> >> > >
>> >> > > The alternative without using BeginUpdate/EndUpdate?
>> >> > >
>> >> > > I found that when setting the Node.Text property the TreeView goes
>> >> > > into
>> >> > > meltdown with literally millions of windows messages and handle
>> >> > > requests initiated through TreeNode.set_Text ->
>> >> > > TreeNode.UpdateNode ->
>> >> > > TreeView.ForceScrollbarUpdate.
>> >> > >
>> >> > > As an experiment I set "Scrollable=false" on the TreeView. Sure
>> >> > > enough,
>> >> > > I now get the equivalent of .Net 1.1 performance when expanding...
>> >> > > but
>> >> > > of course now the treeview is not scrollable. You ask "why not
>> >> > > just
>> >> > > turn that off and on afterwards then"? Because the TreeView
>> >> > > appears
>> >> > > to
>> >> > > completely reset and redraw itself when the Scrollable is set back
>> >> > > to
>> >> > > true which is completely unusable.
>> >> > >
>> >> > > So - I'm knackered if I used EndUpdate, and I'm knackered if I
>> >> > > don't.
>> >> > >
>> >> > > Does anyone have any suggestions? At the moment it is "don't use
>> >> > > .Net
>> >> > > 2.0" which clearly ain't gonna fly long term.
>> >> > >
>> >> > > Many thanks.
>> >> > >
>> >
>