Hi,
I am using groups to restrict the user rearranging columns so that they can only be moved within a group. However assigning the column to a group is really expensive and because of this it I can't use it because it is too slow.To illustrate this I created a simple windows forms project with an ultragrid, an ultratexteditor to enter the number of columns to create, an ultralabel to display the elapsed time and an ultrabutton to kick off the column creation - it just builds a datatable with the number of columns entered, assigns it to the grid and then iterates over the columns assigning each one to one of two groups.Here is the time taken for 100, 200 and 500 columns, as you can see the performance degrades exponentially100 columns: 0.359s200 columns: 1.437s500 columns: 16.563sThe code is here: public partial class Form1 : Form { UltraGridGroup groupA, groupB; public Form1() { InitializeComponent(); groupA = ultraGrid1.Rows.Band.Groups.Add("Group A"); groupB = ultraGrid1.Rows.Band.Groups.Add("Group B"); ultraGrid1.DisplayLayout.Override.AllowColMoving = AllowColMoving.WithinGroup; } private void ultraGrid1_InitializeLayout(object sender, Infragistics.Win.UltraWinGrid.InitializeLayoutEventArgs e) { } private void ultraButton1_Click(object sender, EventArgs e) { DateTime start = DateTime.Now; int columns = int.Parse(ultraTextEditor1.Text); DataTable dt = new DataTable(); for(int i = 0; i < columns; ++i) { dt.Columns.Add(i.ToString()); } ultraGrid1.DataSource = dt; // Assign columns to one of the two groups ultraGrid1.BeginUpdate(); ultraGrid1.Rows.Band.GroupHeadersVisible = false; foreach(UltraGridColumn column in ultraGrid1.Rows.Band.Columns) { column.Group = column.Index < 10 ? groupA : groupB; } ultraGrid1.EndUpdate(); ultraLabel1.Text = (DateTime.Now - start).TotalMilliseconds.ToString(); }Using a profiler on the example with 200 columns I can see that 98% of the time is spent in UltraGridColumn.set_Group, within there it calls UltraGridColumn.GetActualWidth 18,200 times, and the main culprit is the UltraGridBand.get_ConContainsColumnWithVisibleHeaderCheckBoxOnTopOrBottom() function that takes 84.78% of the total time. Internally in total it has created 18,200 enumerators and called MoveNext 3,658,200 times!!!!!In actual fact I do know which group I want each column to be assigned to when I first created the data table, however this is only a grid concept so I have no choice but to manipulate it afterwards.Is there a more efficient way to allocate columns to groups? As it is I will have to give up on groups altogether as it is possible that we have a fair number of columns in our grid.The profiler breakdown looks like this100.00 % ultraButton1_Click - 16317 ms - 1 call - grid_group_perf.Form1.ultraButton1_Click(Object, EventArgs) 98.65 % set_Group - 16096 ms - 200 calls - Infragistics.Win.UltraWinGrid.UltraGridColumn.set_Group(UltraGridGroup) 98.64 % SetGroup - 16095 ms - 200 calls - Infragistics.Win.UltraWinGrid.UltraGridColumn.SetGroup(UltraGridGroup, Int32, Int32) 98.41 % InternalAdd - 16057 ms - 200 calls - Infragistics.Win.UltraWinGrid.GroupColumnsCollection.InternalAdd(UltraGridColumn, Int32, Int32) 98.17 % AdjustGroupWidth - 16018 ms - 200 calls - Infragistics.Win.UltraWinGrid.GroupColumnsCollection.AdjustGroupWidth(Boolean, Boolean, Boolean) 96.42 % GetGroupWidthRange - 15733 ms - 200 calls - Infragistics.Win.UltraWinGrid.GroupColumnsCollection.GetGroupWidthRange(Boolean, Boolean, Int32 &, Int32 &, Int32 &) 95.84 % GetActualWidth - 15637 ms - 18200 calls - Infragistics.Win.UltraWinGrid.UltraGridColumn.GetActualWidth() 95.82 % GetActualWidth - 15635 ms - 18200 calls - Infragistics.Win.UltraWinGrid.UltraGridColumn.GetActualWidth(Boolean) 95.71 % get_Width - 15616 ms - 18200 calls - Infragistics.Win.UltraWinGrid.UltraGridColumn.get_Width() 90.45 % get_CardLabelSize - 14759 ms - 18200 calls - Infragistics.Win.UltraWinGrid.UltraGridColumn.get_CardLabelSize() 90.06 % VerifyCardLabelSizeCache - 14695 ms - 18200 calls - Infragistics.Win.UltraWinGrid.UltraGridColumn.VerifyCardLabelSizeCache() 84.78 % get_ContainsColumnWithVisibleHeaderCheckBoxOnTopOrBottom - 13834 ms - 18200 calls - Infragistics.Win.UltraWinGrid.UltraGridBand.get_ContainsColumnWithVisibleHeaderCheckBoxOnTopOrBottom() 37.30 % get_HeaderCheckBoxAlignmentResolved - 6086 ms - 3640000 calls - Infragistics.Win.UltraWinGrid.UltraGridColumn.get_HeaderCheckBoxAlignmentResolved() 16.25 % get_HiddenResolved - 2652 ms - 3640000 calls - Infragistics.Win.UltraWinGrid.UltraGridColumn.get_HiddenResolved() 13.49 % get_IsHeaderCheckBoxVisible - 2202 ms - 2486250 calls - Infragistics.Win.UltraWinGrid.UltraGridColumn.get_IsHeaderCheckBoxVisible()ThanksMartinp.s. I'm using the latest 2009.1 hotfix
Not sure if you have some other restrictions but using a RowLayout might be another option.
There are some limitations with RowLayouts however.
Nick
Have you read this- WinGrid Performance Guide ?
The section on BeginUpdate and EndUpdate might help.
If that doesn't help, can you post your sample project which demonstrates this so I can take a look? There's really no reason why this should take so long as far as I can see.
Yes I have read the performance guide, the code I posted had already wrapped the group assignment between beginupdate and endupdate calls...
I have attached the full example project for your convenience.
Many thanks,
Martin
Hi Martin,
Yeah, it looks like this is something we should look at improving. There's no reason it should take this long.
I'm forwarding this thread over to the Infragistics Developer Support group so they can write this up for review by the developers. Hopefully, we can do something about this for the next service release.
Hi Mike Saltzman
Have you decided this issue. I have a method SetDataBinding runs longer than 1 second. I looked through dotTrace and determined that the longest-running method get_ConContainsColumnWithVisibleHeaderCheckBoxOnTopOrBottom. Build version Infragistics2.Win.UltraWinGrid.v9.1.20091.2029. Service Release 1 installed.
This was fixed a long time ago, I'm sure. You probably need to get the latest service release.
How to get the latest service release - Infragistics Community
The original bug report here was a bug that was introduced by new functionality. The grid used to add columns to groups fairly quickly, and then the time was drastically increased. So the fix here was to return the grid back to the original level of performance.
But what you're talking about here is essentially a different issue with the performance.
I have not looked at the code, but my guess is that you are probably right. The performance issues probably come from checking to make sure columns are not already in the group before adding them. So this could be improved using Dictionaries or by adding an AddRange method to the group.
I'm not sure what "into consideration" means, but my guess is that they consider this a feature request rather than a bug, since the grid is working as designed.
Just for the record, the performance has been improved slightly in service pack 2, but still not enough for me to be able to use it. This was my response to the support request that was raised for this, I was told my comments would be taken 'into consideration'
So I ran my original sample project again with the latest hotfix and saw the following:100 columns takes 250ms (was 359ms), 200 columns takes 750ms (was 1.437s) and 500 columns takes 4.640s (was 16.5s).While this is an improvement of between 2 to 4 times, I don't think it is much of an improvement - certainly not enough for me to be able to start using it.Just pushing it a bit further, using 1000 columns now takes over 18s to assign the groups - however without the column assignment it takes just 187ms, which is still a factor of 100 longer to assign the columns to groups.
The grid is mainly being used to implement the display of a pivot table, if the user chooses a column pivot field that has a large number of values then it can easily display 1000 columns. If I assign each column to a group the grid will hang for 18s which is clearly not acceptable.I really want to assign every column to only one of two groups (as per the example...), one group is for the columns holding the row pivot fields, then a second group has each value of the column pivot. Doing this means that the column pivot values can be re-ordered within their group by the user but not placed in the row pivot columns and vice versa.
Clearly the grid is doing alot of internal processing when a group is assigned to a column so we want to minimise the amount of times the grid has to do that.
The main problem is that I have to assign a group to every column, and I have to do this a column at a time.Working around either parts of that statement would solve the issue.a) We have to assign a group to every column if any column has a group assigned otherwise the grid throws an exception.If I could assign a default column group to a band that applies to all columns, then I would just need to explicitly set the group on the few columns I want to belong to the different group.
b) Be able to assign a list of columns to a group in a single operation. e.g. provide the following function UltraGridGroup.AddColumns(IEnumerable<UltraGridColumn>)Then I would just need to call this twice which should be reasonably efficient.
c) Prevent processing the column changes within the BeginUpdate and EndUpdate calls.If this could be suspended during BeginUpdate this would be the most efficient solution as the processing would only be done once in EndUpdate regardless of how many groups there were to assign columns to.
Regards,