Archive

Posts Tagged ‘remove’

So you have memory problems in your Flex application?

September 3, 2009 Leave a comment

First, if you aren’t already acquainted with the memory issues in the flash player, browse through some of these links:

Grant Skinner:

Sean Christmann: http://www.craftymind.com/2008/04/09/kick-starting-the-garbage-collector-in-actionscript-3-with-air/

Alex Harui:

Adobe official docs: http://livedocs.adobe.com/flex/3/html/help.html?content=profiler_6.html

I would like to add a technique to the collective knowledge that I have implemented in our MVC framework and propagated through our legacy code base: IDisposable.

The contract of IDisposable is very simple, exposing a lone method: dispose(). An implementation of the interface has the following responsibilities:

  1. Follow the rules of the aforementioned links (e.g. removing event listeners)
  2. Call dispose on any IDisposable children that he is responsible for.
  3. Explicitly set all class level non-simple types to null, including splicing arrays, and deleting dictionary/object keys.

The reason for number 3 is very simple. Take a look at the following diagram taken from the garbage collection overview by Grant:

Credit to Grant Skinner: http://www.gskinner.com/blog/

Credit to Grant Skinner: http://www.gskinner.com/blog/

Since the first pass of the flash garbage collector is based off of reference counting, the goal is to remove all references that you can control in order to optimize for the collector. Let’s see an example.

private var _string1:String = "Don't bother disposing of me";
private var _a:Array;
private var _o1:Object;
private var _o2:Object;
private var _o3:Object;

function ohSnap():void
{
    _o1 = {label: "sweet"};
    _o2 = {label: "awesome", sweet: _o1};
    _o3 = {label: "cool", awesome: _o2, sweet: _o1};
    _a = [_o1, _o2, _o3];
}

Even if this array and collection of objects ends up white in the mark and sweep diagram above, they remain in memory until the second phase of the collector is activated. Why?

Lets count the references of the objects created in ohSnap:
o1: 4 references, by the array, o2, o3, and _o1.
o2: 3 references, by the array, o3, and _o2.
o3: 2 references, by the array and _o3.
a: 1 reference by _a

Now, let’s go on ahead and optimize our destruction by cleaning up these references in our dispose method:

public function dispose():void
{
    for ( var i:int = _a.length-1; i > -1; i-- )
    {
        var o:Object = _a[i];
        for ( var key:String in o )
        {
            delete o[key];
        }
        _a.splice(i, 1);
    }
    _o1 = null;
    _o2 = null;
    _o3 = null;
    _a = null;
}

Deleting the keys of the objects removes the references of o1 in o2 and o3, and o2 in o3, while splicing the array removed the references to o1, o2, and o3. Finally, the class level references to the objects were removed, leaving a reference count of zero for the three objects and array.

In addition to having the marksweep collection method run less because the reference count method removes the objects first, implementing a standard contract in your applications for all objects makes memory management, such as identifying leaks easier because the cleanup of each object is in a standardized place.

Follow

Get every new post delivered to your Inbox.