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
15
populating ultragrid
posted

Hi,

I have a datasource with 10000 rows and 280 columns. It is essential to the project to filter the grid, so I choose LoadStyle.PreloadRows.

Based on the cellcontent an appearances needs to be set. For the project, this is a result of a LINQ query. I use the initialiseRow event to add the correct appearance to the cell. Unfortunately it takes 3 minutes to display the grid.

Is there a way to imporve the performance? I have included a testproject to illustrate the issue.UltraGridMoreLoadData.zip

  • 467290
    Verified Answer
    Offline posted

    Hi Johan,

    I ran your sample and added some code to use a Stopwatch to track the time between when I set the DataSource on the grid and the first time the grid paints. I also separated the creation of the data from the binding of the grid.

                var data = InitializeTable(rows: 10000);
                ultraGrid1.Paint += UltraGrid1_Paint;
                sw = Stopwatch.StartNew();
                ultraGrid1.DataSource = data; // 15 seconds to initialize display

    On my machine, it took about 25 seconds.

    So then I started looking at your code and ways to make it more efficient. Right off the bat, I decided to comment out all the code in InitializeRow just to make sure that was what is causing the performance hit. Sure enough, when I do that, the time is reduced to 8 seconds. So it seems like making the InitializeRow code as efficient as possible is the correct approach.

    When looking at this code, I noticed several ways it could be improved. For one thing, you are getting the column, then getting it's caption, then using the caption to get the cell value. This is not only inefficient, it's also error-prone, since the caption is not necessarily the same as the column's Key. It's a minor issue, but since this code is getting hit a LOT, it makes sense to squeeze out every possible optimization. So, since the column keys are not likely to change, I built a list of the relevant keys once so I could re-use inside of InitializeRow. And, in fact, I think storing the column object itself, rather than the key, is even more efficient, since it will avoid indexing into the Columns collection entirely.

    Also, for each row and each cell, you are indexing into the Appearances collection on the DisplayLayout. This is pretty fast, especially since there are only 2 Appearances in the list, but it's still unnecessary and it's getting hit millions of times. So it makes sense to cache these two appearances in a form-level variable.

    After I changed all that, the time was reduced to about 12-18 seconds. Still quite a long time. But the best I can achieve using this approach. I am attaching a sample here with the changes I made.

    UltraGridMoreLoadData - More efficient.zip

    If this is not good enough, then another approach you could take would be to not use Appearances and instead color the cells using a DrawFilter. This operates at the drawing layer instead of the object model. So it only applies to the cells that are on the screen at any given time. It's therefore a lot faster and more efficient. But the disadvantage is that since you are affecting the drawing layer, the appearances will not be applied to Exporting (although it will work for printing). So if exporting is a concern and something you need in your application, you might have to work around that in another way.

    Another tricky part of using the DrawFilter is that the DrawFilter has to know which column to which it should (and should not) apply the colors. In your sample, you are using the column index, which is generally not a good idea, since the user can re-arrange the columns by default, and that will change the indices. So you need to determine the most efficient way to deal with that hurdle. One very simply way t do this would be to make use of the column's Tag property and simply set the tag to true on the columns you want colored. This is the approach I took in my sample, which is attached here. UltraGridMoreLoadData - DrawFilter.zip

    And finally, for future reference, you might want to check out the WinGrid Performance Guide for any issues relating to performance of the grid.