Drunk on Software Episode 3 – Performance Pitfalls of Flex’s ArrayCollection

Jon and I have posted Episode 3 of the Drunk on Software video podcast. In this episode we talk about some of the real world performance issues with Flex’s ArrayCollection. We’ve also created a few demos which illustrate how in some cases ArrayCollection is 26 times slower than Array:

Let us know what you think.

This entry was posted in Drunk on Software, Flex. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

16 Comments

  1. Posted November 23, 2008 at 11:23 am | Permalink

    Can you guys make those into video podcasts so we can subscribe to them like RIA Weekly

  2. codecraig
    Posted November 23, 2008 at 8:34 pm | Permalink

    Ever try this?

    var data:Array = getDataFromSomewher();

    // dgAC – ArrayCollection bound to a DataGrid

    for each ( var tmp:MyDomainObject in data ) {
    dgAC.source.push( tmp );
    }
    dgAC.refresh();

    This will add the stuff from ‘data’ into the Array that the ‘dgAC’ ArrayCollection wraps without firing events. Then the call to ‘refresh’ fires off an event telling whoever is listening that the contents changed!

    Ever try that??

  3. Posted November 24, 2008 at 9:14 am | Permalink

    Hi codecraig,

    I’ve done that in some instances. The problem however is that when AMF data is deserialized it is very hard to do that. And this also doesn’t solve the problem that instancing a ton of ArrayCollections still takes a long time (which AMF serialization also does when the data set contains a lot of collections). So certainly that will work sometimes. But in the case of AMF being deserialized, aside from custom deserializers, we have little control over how the data is deserialized and ArrayCollection is the default.

    -James

  4. Justin
    Posted November 24, 2008 at 4:34 pm | Permalink

    James, can you provide a in-depth explanation on why an arrayCollection is 26 times slower, or is that already documented?

  5. Posted November 24, 2008 at 4:37 pm | Permalink

    Hi Justin,

    I don’t totally know why it is so much slower than an Array. But if you vote for the bug then hopefully someone will look further into it.

    -James

  6. Posted November 24, 2008 at 4:38 pm | Permalink

    Hi Wade,

    We are looking into how to best do that. Do you use iTunes or just a plain old RSS reader for those?

    -James

  7. Posted November 24, 2008 at 4:57 pm | Permalink

    I am not a very technical person i just use itunes.

  8. Posted November 24, 2008 at 5:04 pm | Permalink

    Perfect then. We will probably be switching to blip.tv which has iTunes support.

  9. Bruce
    Posted November 26, 2008 at 12:22 pm | Permalink

    Have you tried creating the array and assigning the arrayCollection.source to this newly created array and publishing the change of the array collection with ArrayCollection.refresh(). This should get you very very close to Array insert speeds and still give you the events that we so much like with the ArrayCollection. From what I’ve seen the ugliness is in ArrayList with addItem. Event though the ArrayCollection has disableAutoUpdates that just ensures the auto updates are not fired via the ArrayCollection, but since the ArrayList fires events to the ArrayCollection the array collection just doesn’t pass this update along and is still listening when disableAutoUpdates has been activated. If you use this method you shouldn’t have ugliness with the ArrayCollection, if you have something coming from a server (and I believe there is a different kind of list that is created from a server side that replaces the ArrayList) you can have it transported as an Array and then assign the array to .source of an ArrayCollection or hope for the best that the implementation of the ArrayCollection’s list implementation is different or that it doesn’t use addItem/addItemAt.

  10. Alex
    Posted November 27, 2008 at 2:42 am | Permalink

    I never got a real life situation where I need 100.000 Array instances? Do you? I think a more realistic benchmark would be with 1000 object, and for shure that are many objects.

    Greetz
    Alex

  11. Posted November 27, 2008 at 9:21 am | Permalink

    Hi Bruce,

    See the comment above. The problem is that you have very little control over how AMF collections are deserialized.

    -James

  12. Posted November 27, 2008 at 9:23 am | Permalink

    Hi Alex,

    You might not be using large datasets and complex objects graphs but there are certainly many out there who do. My friend Jon encountered this problem on a real project.

    -James

  13. Bruce
    Posted November 27, 2008 at 10:32 am | Permalink

    Okay, so I’m not sure which you’re trying to prove. 1) ArrayCollection vs Array performance is vastly different or 2) The flex serialization engine does not perform as well for Arrays as it does for ArrayCollections? or are you saying because the addItem on ArrayCollection is slow then all operations on the ArrayCollection are slow?

    if 1, i think we can safely say you can use the source array element (when you have large datasets) and get a close comparison of the performance an array gets you.
    if 2, then you should investigate whether there is performance issues with ArrayCollection serialization vs Array serializations. I would bet you would be quite amazed that the underlying serialization method of readExternal doesn’t use addItem or addItemAt but probably serializes the source data which is actually most likely an array. I would bet the ArrayList is even like this.

    So I did a performance test based upon your code but changed the addItem to the .source = myA, then I added the writeObject & readObject of the data. And wouldn’t you know it it’s about 65 millis difference between the two.

    Anyway I’m posting the updated source code

    <![CDATA[
    var i:int;
    myA = [];
    myAC.removeAll();
    myACNAU.disableAutoUpdate();
    myDBAC.removeAll();
    myDDBAC.removeAll();

    var startTime:Date = new Date();
    var b:ByteArray = new ByteArray();
    if( useA.selected )
    {
    for( i = 0 ; i < numObjects.value ; i++ )
    {
    myA.push({prop1:’asdf’, prop2:startTime, prop3:i});
    }
    b.writeObject(myA);
    }
    else if( useAC.selected )
    {
    for( i = 0 ; i < numObjects.value ; i++ )
    {
    myA.push({prop1:’asdf’, prop2:startTime, prop3:i});
    }
    myAC.source = myA;
    myAC.refresh();
    b.writeObject(myAC);
    }
    else if( useACNAU.selected )
    {

    for( i = 0 ; i < numObjects.value ; i++ )
    {
    myA.push({prop1:’asdf’, prop2:startTime, prop3:i});
    }
    myACNAU.source = myA;
    myACNAU.refresh();
    b.writeObject(myACNAU);
    }
    else if( useDBAC.selected )
    {
    for( i = 0 ; i < numObjects.value ; i++ )
    {
    myA.push({prop1:’asdf’, prop2:startTime, prop3:i});
    }
    myDBAC.source = myA;
    myDBAC.refresh();
    b.writeObject(myDBAC);
    }
    else if( useDDBAC.selected )
    {
    for( i = 0 ; i

    @James Ward

  14. Posted November 27, 2008 at 2:26 pm | Permalink

    @Bruce

    The scenario in which the problem was discovered is a very large project with thousands of classes in an object graph. When an initial request at application startup is made to the server hundreds of thousands of objects are turned into AMF and sent back to the Flex applications. The deserialization was taking a very long time on the client. The reason turned out to be the amount of time it takes to instantiate and add items to ArrayCollections. Arrays are much faster but require a lot of extra work to deal with. There is not a good way to specify which collections should use Arrays and which should use ArrayCollections. Also creating custom serialization (read/write External) would be way too much work. Ideally Flex would deal with this scenario in a more efficient manner.

    -James

  15. Joey
    Posted November 28, 2008 at 9:38 pm | Permalink

    Hi James,
    First off, thank you for sharing. – Second, I am totally confused when it comes to AMF. Unfortunately, I don’t have the option of installing additional software such as LCDS, BlazeDS, OrbWeb, etc… so there is no way for me to test AMF that I am aware of.

    I built a simple reporting app for my department. Presently, I use the webservice component and hook it up to a .NET webservice. Depending on the webservice it will return either an ArrayList of objects or a DataTable. In either case, Flex populates an Array (ArrayList) and an ArrayCollection(DataTable) which is then used for databinding. My questions to you are …

    1. ArrayList or DataTable – which would you prefer when using/not using AMF?

    2. Is my approach correct? If not, what approach would you take? Using my approach, which would yield better results – with/without AMF?

    3. When creating an app with features such as friends list, photo sharing, etc…. would you recommend using Flex? If so, with/without AMF, and using an array or arrayCollection?

  16. Posted November 28, 2008 at 10:59 pm | Permalink

    Hi Joey,

    XML works fine when you have small data sets and do not control what is on the other side. In this case I’d stick with what works best which is probably Flex with ArrayCollections.

    -James

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Subscribe without commenting