XML E4X Expression Performance
If you deal with XML documents, you probably appreciate AS3’s support for the E4X operators. These make it really easy to access the XML
class like any old object with the .x
(dot) operator as well as XML-specific operators like ..x
for descendants and @x
for attributes. Even fancier, there’s support for arbitrary expressions like .(@id == "123")
. With all this convenience we should wonder- how slow are the E4X expressions?
The docs don’t give much information about what you can do with E4X expressions, but they’re generally like other AS3 expressions. The basic form is like this:
xml.(@id == "123")
That will return all elements with an attribute that is “123”. You can use other comparison operators if you convert the attribute string to a numeric value:
xml.(Number(@id) > 123)
The expression can grow more and more complex as you add logical and (&&
) and or (||
) operators:
xml.(@name == "Smith" && Number(@age) >= 18)
In this example, it’ll return elements where the name
attribute is “Smith” and the age
attribute is greater than or equal to 18.
So, how does this compare to a more manual approach? These simple E4X expressions can be re-written with a for-each
loop combined with an if
check. Here’s the manual version of @id == "123"
:
for each (var elem:XML in xml) { if (elem.@id == "123") { // do something with the element } }
Now to test the E4X version against the manual version:
package { import flash.display.*; import flash.utils.*; import flash.text.*; public class E4XTest extends Sprite { private var logger:TextField = new TextField(); private function row(...cols): void { logger.appendText(cols.join(",") + "\n"); } public function E4XTest() { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; logger.autoSize = TextFieldAutoSize.LEFT; addChild(logger); init(); } private function init(): void { const REPS:int = 1000; const SIZE:int = 1000; var i:int; var beforeTime:int; var afterTime:int; var elem:XML; var count:int; var xmlStr:String = "<xml>"; for (i = 0; i < SIZE; ++i) { xmlStr += '<elem id="' + i + '"/>'; } xmlStr += "</xml>"; var xml:XML = XML(xmlStr); row("Operation", "Time"); count = 0; beforeTime = getTimer(); for (i = 0; i < REPS; ++i) { for each (elem in xml.elem.(@id == "0")) { count++; } } afterTime = getTimer(); row("E4X", (afterTime-beforeTime)); beforeTime = getTimer(); for (i = 0; i < REPS; ++i) { for each (elem in xml.elem) { if (elem.@id == "0") { count++; } } } afterTime = getTimer(); row("Manual", (afterTime-beforeTime)); } } }
I ran this test in the following environment:
- Release version of Flash Player 12.0.0.44
- 2.3 Ghz Intel Core i7-3615QM
- Mac OS X 10.9.1
- Google Chrome 32.0.1700.107
- ASC 2.0.0 build 354071 (
-debug=false -verbose-stacktraces=false -inline -optimize=true
)
And here are the results I got:
Operation | Time |
---|---|
E4X | 950 |
Manual | 813 |
Both versions are searching all the elements in the XML
object, but the E4X version is taking 17% longer. This isn’t hugely slower than the manual version and arguably a lot cleaner, so you may opt to use it in areas of code that aren’t performance-critical. Still, as with the recommendation of previous XML articles, you should probably parse the XML
object into a typed class
instance for maximum performance.
Spot a bug? Have a question or suggestion? Post a comment!
#1 by Tyler on February 10th, 2014 ·
E4X in AS3 has really spoiled me with these sorts of features. It makes me dread working with XML in just about every other language. The performance isn’t great, but XML parsing almost always seems to be done at non-performance-critical times, so it hasn’t been an issue for me. Have you found any other languages that make working with XML as fun?