Sunday, March 4, 2012

Android XML Parsing/Serialization


Currently I'm working on a project for my university. The goal is to write a UPNP (Universal Plug and Play) control point for Android. Due to the nature of SOAP, which is used to interact with the different devices, we were confronted with a lot of XML parsing and serialization. To keep the code relatively clean and simple we decided to use "Simple", a Java framework for serialization and deserialization. All you have to do to generate XML with Simple is:

  • Annotate your Java classes.
  • Pass your object to a persister which generates the XML based on your annotations.

To parse XML you pass the XML to an instance of the persister and it will return an object.
Sounds simple and it is! So what is the downside? Halfway through the project we noticed that our browse requests were unbearable slow.  So I decided to figure out where the problem was. Using the android traceview tool it turned out that serialization of the request, as well as the parsing of the response took way to long.  After looking deeper into the generated trace log file the actual problem showed up,  reflections.

So what were the alternatives? 
Writing a SAX-based parser - Too much work to handle the current state, position in the XML.

A DOM-based parser - Another drawback of Simple was that due to a missing StAX implementation for Android it made use of DOM. In the beginning we were willing to accept the memory usage drawbacks that come with DOM, but if you get another chance why should you make the same mistake again?

A XML Pull Parser (XPP) - "Using XMLPullParser is an efficient and maintainable way to parse XML on Android." Jesse Wilson
This turned out to be our way of choice.  XMLPullParsers are better maintainable than SAX-Parsers and since you "build" your objects while you pull in the XML you are able to keep a lower memory footprint than with DOM.

Another bottleneck StringEscapeUtils XML unescape method
It seems the version of the StringEscapeUtils (3.1) we were using looks up every character of a String you pass in a HashMap (source reference). This was different in previous versions where the HashMap was only checked when an ampersand occurred.


Changing from Simple to KXML and to a custom unescape method speed up the BrowseRequest about 25 times (excluding the network delay).
But let the charts speak for themselves:



Table - Parsing of XML on Android (Time in seconds)










Chart - Comparsion of parsing process 









Process of serialization