XML is widely used in AS3 applications for everything from simple configuration files to complex networking protocols. AS3 even includes 10 operators in its syntax specifically to make XML easier to work with. This often leads to AS3 developers loading XML documents and then just leaving them as an XML objects. XML’s performance begins to seep into the rest of the AS3 application. Today we look at just how much this can slow down our apps.

XML is usually loaded from a text file with a class like URLLoader and constructed by passing the loaded String to the XML constructor. However, if you need to build one yourself, you can do so in a variety of ways. In the below test app, I use appendChild to add sub-elements to the root of the XML document. You might do something similar if you needed to construct an XML file for saving to disk (in the case of AIR) or passing to an XML-based web API.

In contrast to XML, Object and Dictionary are used all the time by AS3 programmers in need of a generalized key-value map. These are pure data structures that are less related to a file format than XML is, but are often the format of choice for generic data file parsers such as those decoding JSON files.

The below test app creates some large XML, Object, and Dictionary and measures the time it takes do do so. It then reads all of the elements of each collection object to test the access speed.

package
{
	import flash.display.*;
	import flash.utils.*;
	import flash.text.*;
 
	public class XMLSpeed extends Sprite
	{
		private var __logger:TextField = new TextField();
		private function log(msg:*): void { __logger.appendText(msg + "\n"); }
 
		public function XMLSpeed()
		{
			__logger.autoSize = TextFieldAutoSize.LEFT;
			addChild(__logger);
 
			const SIZE:int = 10000;
			var beforeTime:int;
			var afterTime:int;
			var i:int;
			var xml:XML = <root/>;
			var obj:Object = {};
			var dict:Dictionary = new Dictionary();
 
			log("Build");
			log("Container,Time");
 
			beforeTime = getTimer();
			for (i = 0; i < SIZE; ++i)
			{
				xml.appendChild("child"+i);
			}
			afterTime = getTimer();
			log("XML," + (afterTime-beforeTime));
 
			beforeTime = getTimer();
			for (i = 0; i < SIZE; ++i)
			{
				obj["child"+i] = true;
			}
			afterTime = getTimer();
			log("Object," + (afterTime-beforeTime));
 
			beforeTime = getTimer();
			for (i = 0; i < SIZE; ++i)
			{
				dict["child"+i] = true;
			}
			afterTime = getTimer();
			log("Dictionary," + (afterTime-beforeTime));
 
			log("");
			log("Access");
			log("Container,Time");
 
			beforeTime = getTimer();
			for (i = 0; i < SIZE; ++i)
			{
				xml.child("child"+i);
			}
			afterTime = getTimer();
			log("XML," + (afterTime-beforeTime));
 
			beforeTime = getTimer();
			for (i = 0; i < SIZE; ++i)
			{
				obj["child"+i];
			}
			afterTime = getTimer();
			log("Object," + (afterTime-beforeTime));
 
			beforeTime = getTimer();
			for (i = 0; i < SIZE; ++i)
			{
				dict["child"+i];
			}
			afterTime = getTimer();
			log("Dictionary," + (afterTime-beforeTime));
		}
	}
}

Here is the test environment I ran this app on:

  • Flex SDK (MXMLC) 4.1.0.16076, compiling in release mode (no debugging or verbose stack traces)
  • Release version of Flash Player 10.2.154.27
  • 2.4 Ghz Intel Core i5
  • Mac OS X 10.6.7

And here are the results I got:

Build
Container Time
XML 4277
Object 10
Dictionary 7
Access
Container Time
XML 2126
Object 6
Dictionary 5

The results are even more striking in graph form:

Creation performance

Access performance

At both creation and access, XML is tremendously slower than either Object or Dictionary. If you’re keeping around an XML object that you’ve loaded and querying it on a regular basis (many times per frame, for example), consider either converting the XML object to a plain Object or Dictionary or, for the ultimate speed boost, storing them as typed fields of a class. At a performance penalty of 400x, it may very well be worth it all on its own.