Memory Management in Flash Lite and ActionScript 2 using ASUnit

In my new position the team I have joined and me are carying out some in depth testing of an Action Script 2 code base for Flash Lite 3 using, among other things, ASUnit based unit and acceptance tests. The early stage of development means it is too soon to leverage the new automated testing features of Adobe Device Central CS4. One of the most important aspects of our testing has been to check memory use over the lifetime of the applications we are developing. We are interested in tracking any memory leaks in our code and also any memory space fragmentation as the Flash Lite player creates or destroys objects and classes.

This memory information is viewable from Adobe Device Central in the Memory Panel, where device central provides a graph showing memory usage over time, separating Static Heap and Dynamic Heap consumption of the player as your Flash Lite application runs.

MemoryPanel.png

Testing for memory use, loss and leaks is currently not present as standard in ASUnit for ActionScript 2. In order to include this form of testing at a basic level we have employed a trick I picked up at Max San Francisco this year (If you are the person that explained the trick, please leave a comment so I can credit you). The technique makes use of the FlashLite SharedObject as a way of measuring the file size of objects and classes before and after you think you have destroyed them in your code.

The premiss is a simple one. In your test as part of the test setup create a local SharedObject create an empty data property and save the SharedObject to disk, then call the SharedObject.getSize() method and store the size of your empty SharedObject. The code should look something like this.

// size variation threshold for the SharedObject
private static var SIZEVARIANCE:Number = 5;
private var iS:SharedObject;
private var iSSize:Number;
// standard ASUnit test setup
private function setUp():Void
{
instance = new TestableClassObject();
iS = SharedObject.getLocal("iS");
iS.clear();
iS.data.iS = undefined;
iS.flush();
iSSize = iS.getSize();
}

Some things to keep in mind are the following. The length of the SharedObject name and the length of the data property name will have an impact on the result of SharedObject.getSize(). In the above example I have limited both these values to 2 characters (‘iS’). All that remains is to link the value obtained from this setup function into a standard ASUnit test which looks something like this:

public function testDestroy():Void
{
instance.destroy();
iS.data.iS = instance;
assertTrue("testDestroy : test that the TestableClassObject 'instance' is destroyed successfully by checking size variation (" + SIZEVARIANCE + ") in SharedObject", ((iS.getSize() - iSSize) < SIZEVARIANCE));
}

In this test I am simply calling the target class instance’s destroy method, which should manage the removal of any stored references, arrays and object present in the class. I then save the locally stored instance back to the existing shared object, re-call SharedObject.getSize() and compare the size difference to the value of our initial empty SharedObject (iSSize) from the test setup method.

If the file size of the SharedObject is greater than the SIZEVARIANCE threshold then the test will fail. If that is the case then you have the ability to inspect the shared object using a SharedObject viewer (I use the free Solve by Darron Schall). In the viewer you will be able to see what items are not being properly removed from your class instance oronject. A common issue I have seen is the failure to destroy arrays that are prpperties of my classes for example. Some time over the holiday break I will put together a full example for download.

One thought on “Memory Management in Flash Lite and ActionScript 2 using ASUnit”

Leave a Reply

Your email address will not be published. Required fields are marked *