Dealing with XML files can very easily trigger Flash to “leak” memory. Your app may only keep a tiny fraction of the XML file’s contents, but the whole file may stay in memory and never get garbage collected. Today’s article examines how this happens and how you can clean up all that unused memory.

This particular memory “leak” stems from a peculiar behavior in Flash where strings that are built from other strings do not actually have a copy of the original string’s characters. Instead, they have a “master string” field which references the characters in the original string. In a debug version of Flash Player you can see the contents of the “master string” using the flash.sampler.getMasterString. Consider the following example:

var str:String = "ABCDEFGHIJKLMNOPQRSTUV".substr(0,2);
trace(str + " has master string " + flash.sampler.getMasterString(str));
// output: AB has master string ABCDEFGHIJKLMNOPQRSTUV

Even though you’re only using the “AB” string, Flash is holding the whole “ABCDEFGHIJKLMNOPQRSTUV” string in memory since that’s what “AB” was built from. While a few letters of the alphabet is just fine, the problem can get out of control when you’re dealing with huge XML files. What if all you did was save one tiny string from the XML to a variable? As it turns out, the entire XML file will stay in memory in this case. To illustrate, here’s a small example:

var xml:XML = new XML(
	'<people><person first="John"/><person first="Mary"/></people>'
);
xmlJohn = xml.person[0].@first;
trace(xmlJohn + " has master string " + flash.sampler.getMasterString(xmlJohn));
// output: John has master string <people><person first="John"/><person first="Mary"/></people>

How about JSON? Does the same problem happen there, too? Luckily, it does not:

var json:Object = JSON.parse(
	'{"people":[{"first":"John"},{"first":"Mary"}]}'
);
jsonJohn = json.people[0].first;
trace(jsonJohn + " has master string " + flash.sampler.getMasterString(jsonJohn));
// output: John has master string null

So what do you do if you want to get rid of all that master string baggage from the XML file? To solve that issue I’ve created a tiny static function that modifies the string just enough to convince the Flash Player to dump its master string. Feel free to use this in your own projects:

/**
*   Replace a string's "master string"-- the string it was built from-- with a single
*   character to save memory.
*   @param str String to clean
*   @return The input string, but with a master string only one character larger than it
*   @author JacksonDunstan.com/articles/2260
*/
public static function cleanMasterString(str:String): String
{
	return ("_"+str).substr(1);
}

With this function the master string will be simply “_John”.

Finally, I’ve created a small example application to test strings from XML, JSON, and “cleaned” strings from XML using the above utility function. You’ll need a debug version of Flash Player to run it since it uses flash.sampler.getMasterString.

Have a better way of cleaning master strings? Run into this problem in your own app? Spot a bug? Post a comment!