14 Replies Latest reply on Sep 25, 2009 1:41 AM by mraak

    Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows

    mraak Level 1

      I'm doing this locally, no server side.

       

      First I create a fairly large ArrayCollection with 1000 objects, each has 40 properties. Then in the mx:Application i create a DataGrid with 40 columns and use binding for dataProvider. Performance is so slow it struggles for 20 seconds to render this. Is this normal, we're talking about local data here, no server loading.

       

      Where is this slowness coming from? Is it avoidable, I don't think so, but still there has to be a way, otherwise this is useless. Thanks for any tips.

       

      onCreationComplete{

                     [Bindable]

                      col1 = new ArrayCollection();

                    
                      for(var i:int = 0; i < 1000; i ++)
                      {
                          var o:Object = new Object();
                          col1.addItem(o);

       

                          for(var j:int = 0; j < 40; j ++)
                          {
                              var colm:String = (Utils.alphabet[j] as String).toLowerCase();
                              o[colm] = "col1 " + colm + " " + i;

                          }
                      }

       

      }

       

       

      <mx:DataGrid dataProvider="{col1}">

        // 40 columns here

      <mx:DataGrid>

        • 1. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
          Flex harUI Adobe Employee

          The performance profiler will tell you where the time is going.

           

          Adding 1000 items one at a time is highly inefficient as change events have to get dispatched for each one.  Better to fill an array and replace the source.  Also make sure your renderers are optimized.

           

          Alex Harui

          Flex SDK Developer

          Adobe Systems Inc.

          Blog: http://blogs.adobe.com/aharui

          • 2. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
            mraak Level 1

            Should i look at cummulative time or self time? Self time gives me some weird functions on top like [verify], [abc-decode], etc. Don't know what use it has really. The only larger value in self time is the part where I create the ArrayCollection - 102 ms, which is like nothing.

             

            Can you please expand more on how to use the array and then replace the source?

             

            Item renderers should be optimized as I'm using default ones.

             

            Thanks

            • 3. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
              Flex harUI Adobe Employee

              onCreationComplete{

               

                            

               

                              col1 = new ArrayCollection();

                            arr1 = new Array();

               

                              

                              for(var i:int = 0; i < 1000; i ++)

                              {

                                  var o:Object = new Object();

                                  arr1.push(o);

               

               

                                  for(var j:int = 0; j < 40; j ++)

                                  {

                                      var colm:String = (Utils.alphabet[j] as String).toLowerCase();

                                      o[colm] = "col1 " + colm + " " + i;

               

                                  }

                              }

                              col1.source = arr1;

               

               

              }

               

              BTW, looking at your code closer, this is a 40000 item loop with string searching so that is going to be expensive.  If Utils.alphabet[j] is constant, I'd run toLowerCase on it once before the loop

               

              Alex Harui

              Flex SDK Developer

              Adobe Systems Inc.

              Blog: http://blogs.adobe.com/aharui

              • 4. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
                mraak Level 1

                Hi, there's no improvement whatsoever unfortunately. I've been using same that you showed also previously. The bottleneck IMO is not the creation of the data, but rather something internaly in the DG.

                 

                I can't even Google it, everybody talks about how to increase the performance for OTW loading of large data, like the problem isn't there locally. But it is, in my simple example if you run it, even with the improvements you proposed it is useless. I can't believe it can be such a showstopper, I must be doing something wrong.

                • 5. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
                  Flex harUI Adobe Employee

                  I would change the app to go through various steps on pushing various buttons.  For example, get rid of the creationComplete handler and make it the click handler of a button.

                   

                  Then in the performance profiler, turn on both performance profiling and memory profiling, clear the profile samples, click the button, wait until the DG renders, take the performance snapshot and see what it says.  If you need more intermediate steps, add more buttons.

                   

                  Interpreting the data is a bit of an art.  If the set of samples covered 20 seconds, I would first look for large self-times, then large cumulative times.

                   

                  Alex Harui

                  Flex SDK Developer

                  Adobe Systems Inc.

                  Blog: http://blogs.adobe.com/aharui

                  • 6. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
                    mraak Level 1

                    Did that, I'm creating the data for data provider in createData() function after I click on the button. Before that nothing happens. It still takes a lot of time, and oddly enough, there is no createData() function in the performance profile grid. Both button and the function are located in the application tag.

                     

                    Self times and cumulative times are very similar, these are self, now for only 500 rows and still amazingly slow.

                     

                    flash.utils.Timer.tick           10189 (41%)

                    [pre-render]                         3618 (14%)

                    [reap]                                  2571 (10%)

                    [mouse-event]                      1007 (4%)

                    etc.

                    • 7. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
                      Flex harUI Adobe Employee

                      The profiler is a sampling profiler so it can alias in some situations.  If you check the box for memory profiling as well as performance profiling, the performance profiler will use memory allocation samples as well which will provide better resolution, but can still alias if a function doesn't actually do any allocations.  You can artificially alter your profile by allocating things in functions to increase the odds that it will show up in the profiler (even a try/catch block will cause an allocation).

                       

                      Self and cumulative times will be the same if the samples never caught the code in a function called from that function.

                       

                      Make sure you've removed all of the filters.

                       

                      The data you posted here says you spend 10 seconds in a timer tick and another 3.6 rendering the screen. And 2.5 in garbage collection.

                       

                      If the timer tick called something that took a long time it should show up in the profile.  Or maybe the call count is high and it just got called often.

                       

                      Alex Harui

                      Flex SDK Developer

                      Adobe Systems Inc.

                      Blog: http://blogs.adobe.com/aharui

                      • 8. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
                        mraak Level 1

                        Ok I did find the function once after many tries with catch statement. It shows 35ms (1.48%), so this can't be it. Considering I have only a DG and arrayCollection in the app, ain't there a way to "know" how to increase the performance, if possible anyhow, without the profiler? I can't even change anything because as I said I have only two things in the app, the DG and AC, it can't get any simpler.

                        • 9. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
                          Flex harUI Adobe Employee

                          To me, the profiler should be the "truth". It is odd that you aren't getting good numbers, but the timer tick seemed to be responsible for 10 seconds so you need to dig into that a bit.

                           

                          You can run some experiments to see if the time is dependent on the number of rows in the DP or the number of visible rows * number of visible columns.  You can run an experiment using a different data source as well.

                           

                          Alex Harui

                          Flex SDK Developer

                          Adobe Systems Inc.

                          Blog: http://blogs.adobe.com/aharui

                          • 10. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
                            mraak Level 1

                            Will try, but just out of curiosity

                             

                            - Did you try it yourself and how smoothly did it work?

                            - Is there a way to defer rendering or population of dataProvider only when it's scrolled to the visible area?

                            - Should I use a timer and add 100 records each 100ms or so to the AC and then at least I could show a nice progress bar instead of hung app and browser?

                             

                             

                            Cheers

                            • 11. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
                              Flex harUI Adobe Employee

                              I haven't tried it yet.  I don't have all of your parameters like number of visible columns, scrollPolicies, binding, etc.  I've seen tons of test cases shovel lots of data into a DG and it didn't take 20 seconds.  If you can fit an entire test case into 40 lines or so, just post the whole thing.

                               

                              Alex Harui

                              Flex SDK Developer

                              Adobe Systems Inc.

                              Blog: http://blogs.adobe.com/aharui

                              • 12. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
                                mraak Level 1

                                Here you go. But I just noticed another thing also.

                                 

                                A) If I set rowCount=1000 as a property of DG, it takes forever

                                 

                                B) If I leave that out it populates it in a second, but it only gives me few rows and a scroller.

                                 

                                C) If I set rowCount=40 which would be ideal, scroll does not work, and I can only scroll to the 40th row.

                                 

                                I imagine with some settings I could get the perfomance of A and visible area as in C. What else could I change? rowCount works weirdly, height also doesn't do the trick. I feel I'm getting closer now.

                                • 13. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
                                  paul.williams Level 4

                                  The docs aren't particularly clear on the precise meaning of rowCount:

                                   

                                  A) Setting rowCount to 1000 causes the datagrid to create and display 1000 rows each with 1000 * 40 item renderers, regardless of how many are actually visible on screen. Hence the performance issue. The scrollbar you see in this case will be on the application, not the datagrid.


                                  B) Leaving rowcount out will cause the datagrid to size itself using its height property. A scrollbar will be displayed if the total number of rows cannot be displayed within this height. In this case the grid will generate sufficient renderers for all visible rows and then reuse this set of renderes as you scroll (to avoid performance problems). If you haven't specified a height it will use a default value which is quite small.

                                   

                                  C) Setting rowCount to 40 causes the datagrid to create and display 40 rows regardless of how many are in the underlying collection. Hence no scrollbar.

                                   

                                  Try option B again, but specify a height of 100%. If you want an exact number of rows to be visible onscreen plus a scrollbar, you will need to calculate the correct height, eg:

                                   

                                       height={ dg.rowHeight * 40 }

                                   

                                  You may need to specify a fixed rowHeight for this to work.

                                  • 14. Re: Terrible performance ArrayCollection {bind} DataGrid.dataProvider, with 1k rows
                                    mraak Level 1

                                    Yes, I just noticed, seems like to right way to go about is is using height.