Hi,
I'm having some issues with the performance of the ultrawingrid. In my situation, I have a grid with a group by column and about 8000 rows. I need to loop through the individual rows to set values to some unbound columns. However, rather than the assigning of those values, just the looping through the rows (actually: getting the enumerator) causes a delay of a few seconds.
I created a small sample project demonstrating the problem. The project groups a column in the grid and fills it's datasource with 10000 rows. When clicking the test button, it refills the datasource, and loops through the rows. This takes a few seconds, and is too long for a smooth user experience.
My question is, how can I speed up the enumeration of the rows?
I already tried the SuspendUpdate and SuspendRowSynchronization as mentioned in the performance guide, but that didn't help. I also tried the GetRowEnumerator method, but that didn't help either. I hope you can. Thanks in advance.
I'm using version 10.3.20103.1000
Your private case has reference number CAS-122714-L3F8X2. Please take a look on it for more details https://es.infragistics.com/my-account/support-activity/
Let me know if you have any questions.
TorX said:Thanks! I would appreciate it if you can look into this, because I still think it's a little strange why it takes much longer when grouped than not grouped.
I will ask Infragistics Developer support to write this up for developer review so we can check it out.
TorX said:Second, the code you provided does not work for me, I still get the same delay. Is it possible that something is missing from that code?
I have attached my modified sample that works for me.
I added a bunch of code for a StopWatch to time how long the operations take and when the grid and label paint after it's done.
On my machine, without the workaround, the DoPerformanceTest is nearly instantaneous - it takes under 50 milliseconds. The Paint event of the grid occurs over 3 full seconds later, and then the label paints almost immediately after that. So it's clear that the grid is doing some kind of batch processing that's taking a long time. It's probably a results of the grid catching up on 1001 individual data source operations (one clear and 1000 adds).
With the workaround, the painting of the grid only takes about 300 milliseconds (one tenth the time as without the workaround).
If you are still seeing the same issue in my updated sample, then it could be because I am using the latest service release of NetAdvantage 10.3 and you are using an older version.
Thanks! I would appreciate it if you can look into this, because I still think it's a little strange why it takes much longer when grouped than not grouped.
I am a little bit confused by your workarounds though. To answer your first question, I'm removing and re-adding the rows (with different data each time in my business application of course) because I'd like to keep any changes the user has made to column order, widths and grouping. I always use the InitializeLayout event to set default column ordering and widths, and resetting the DataSource fires that event.
Second, the code you provided does not work for me, I still get the same delay. Is it possible that something is missing from that code?
However, the changes you made in that code could in fact help me. The problem I just mentioned about the InitializeLayout event getting fired after setting the DataSource, can be solved by cloning and restoring the layout. I didn't know this trick, and can certainly be helpful.
Do you think this is the way to go, or is there a better solution?
I tried out your sample and it seems that the time is being taken up by the grid painting.
Your code is performing a whole bunch of operations on the data source, which sends over a thousand notifications to the grid, but all of these are being handled almost instantaneously - the grid is just marking the appropriate objects dirty.
When the operation completes, the grid has to paint. At this point, the grid has an entirely different set of rows then it did when it started so it has to rebuild the entire Rows collection and re-group all of the rows. So this is what must be taking up the time. But it's interesting, because if I just ungroup and regroup the grid, it's pretty fast and doesn't take anywhere near as much time. It's also much faster when you run the same code the first time (in Form_Load), probably because the grid is optimized before the first time it paints.
We could look into this and see what's going on, and maybe there is some way we could make this process more efficient. But frankly, I'm not sure it's something we could fix. The grid might be doing some necessary process to completely rebuild the entire set of rows.
What your code is doing here is a bit unusual and inefficient. Why remove all of the rows from the grid and re-add them? If you want to do something like that, it would be a lot more efficient to simple assign a new data source to the grid so that it happens in one operation instead of 1000 operations.
If that's not a viable option, then another workaround I stumbled onto is saving the layout before your operations begin and then restoring it afterward.
private void FillItems() { Infragistics.Win.UltraWinGrid.UltraGridLayout layout = this.ultraGrid1.DisplayLayout.Clone(); Items.Clear(); for (var i = 0; i < 10000; i++) Items.Add(new Foo(i.ToString(), GetGroup(i))); this.ultraGrid1.DisplayLayout.CopyFrom(layout); }
Just a guess, but I think this works because something about what you are doing to the data source is leaving the layout in a weird state and this simply clears it out - in a way telling it to just start over instead of whatever it's doing that's slowing it down.
After more examining, it seems the InitializeRow is not relevant for my problem. Please replace the form code in my sample with the code below. I've removed the enumeration. Because the label's text is changed immediately, the timer is no use anymore, so I replaced it with a counter. As you can see, it takes a while before the label is updated (GUI is frozen). If you ungroup the 'Group' column, the label is updated very fast (desired result).
public partial class Form1 : Form { private readonly BindingList<Foo> Items = new BindingList<Foo>(); private int Counter; public Form1() { InitializeComponent(); } private void DoPerformanceTest() { FillItems(); ultraLabel1.Text = (++Counter).ToString(); } private void FillItems() { Items.Clear(); for (var i = 0; i < 10000; i++) Items.Add(new Foo(i.ToString(), GetGroup(i))); } private string GetGroup(int i) { var c1 = (char)(65 + ((i / 26) % 15)); var c2 = (char)(65 + (i % 26)); return c1.ToString() + c2.ToString(); } private void Form1_Load(object sender, EventArgs e) { ultraGrid1.DataSource = Items; ultraGrid1.DisplayLayout.Bands[0].SortedColumns.Add("Group", false, true); FillItems(); } private void ultraButton1_Click(object sender, EventArgs e) { DoPerformanceTest(); } }