Your Privacy Matters: We use our own and third-party cookies to improve your experience on our website. By continuing to use the website we understand that you accept their use. Cookie Policy
505
Assigning columns to groups is _very_ slow
posted

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 exponentially
100 columns: 0.359s
200 columns: 1.437s
500 columns: 16.563s

The 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 this
100.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()


Thanks

Martin

p.s. I'm using the latest 2009.1 hotfix