Communicating with web services you have to decide on a way to transport the date back and forth. Recently – with the help of the popular Twitter-API – JSON seems to have come ahead in the race. Other contenders are property lists and XML. Property Lists (PLISTs) are available in XML-Text and a binary (“old”) format and are widely supported in the Apple APIs which makes them a joy to work with.
JSON files on the other hand are easy to be generated server-side as they are basically just concatenated text, much less verbose than pure XML. The binary alternative might also be a contender when it comes to performance in transmission and parsing, provided some component is installed on the server to generate them.
In this blog article we are trying to answer the question once and for all what you should use in your own apps.
Martin Brugger from Austrian iOS development company BytePoets spent a lot of time researching the hard facts for us, so that we have a solid base for our analysis. In part this work is based on what Sam Soffes previously published on the performance of a variety of JSON benchmarks. He created a new GitHub project for his benchmarks which are using all the latest version of all JSON toolkits from where you can check out the code for yourself.
These experiments specifically excluded raw XML parsing because the NSXMLParser that comes with iOS is using the sequential SAX method and thus the results cannot be easily compared to JSON and PLIST which take in text and output NSDictionary or NSArray objects. Most of the data types in JSON and all of the ones in PLISTs map to typed Objective-C objects, in contrast to XML where you don’t have such a built in schema. Thus pure XML might be more flexible, but at the same time you have to jump through hoops to get strong typing. It’s a non-starter in today’s race.
So the contestors in our race where:
- YAJL
- JSONKit
- TouchJSON
- JSON Framework
- Apple’s JSON Framework (private)
- Property List (XML)
- Property List (Binary)
One interesting thing that Soffes had uncovered was that Apple indeed has their own highly performant private API for parsing JSON. Sam reconstructed the necessary headers and so it’s another interesting contender to see here, even though we are not allowed to use the JSON.framework in our app store apps. Pity, it’s quite fast.
The amazing race
To get even more relevant data Brugger benchmarked the serialization and deserialization of an array and a dictionary of 1000 entries each) and the standard Twitter JSON. Since the latter cannot be mappted into property lists, this test was excluded for PLISTs.
Here are the writing results, shorter bars are better.
As you can see there is a wide variety between the various toolkits. Arrays, Dictionaries and Twitter’s JSON take varying amounts of time to process. We immediately see the winner: JSONKit, which was just recently updated to version 1.4. Second place goes to property lists, where – curiously – there is almost no difference between the binary and XML formats. Then there is the JSON Framework on the third spot, winning over the private Apple API ever so slightly.
I get the feeling that the low level optimization work that’s been put into JSONKit as well as being carried out by smart Apple engineers is responsible for this result.
Let’s have a look at the reading performance. This is probably the more important one of both benchmarks since most of the data on your mobile device will be received and consumed. Here the verdict is a little more complex than just stating places. Just as with the writing benchmarks arrays are generally quicker to process. This part is again clearly won by JSONKit, closely followed by binary PLIST. Third place is split between YaJL and Apple JSON.
If the consumed data is a big dictionary the clear winner is the binary property list, followed by JSONKit and Apple JSON. YAJL and XML PLIST share the forth place.
When it comes to “real life” scenarios – like parsing the Twitter JSON – property lists cannot compete unfortunately, so here’s another clear win for JSONKit. This is by a wide margin as the second YAJL and the third Apple JSON are orders of magnitude slower.
Does size matter?
Now another question we set out to answer revolves around the time it takes for JSON or PLIST data to be transferred to the client. This is a function of the size, the smaller it is even without compression, the faster it has travelled over the pipe.
My hunch was that binary PLISTs would be way smaller then everything else, but I was proven wrong as you can see from the following chart:
The NSArray is a third larger expressed as XML PLIST than as JSON, the NSDictionary is even twice as large. The binary PLIST is about the same, so much less of a dramatic difference than I had expected.
Conclusion
In terms of transfer speed any plain-text format like XML or XML Plist loses against the compactness of JSON or binary PLISTs. But as stated earlier the difference between BPLIST and JSON can be disregarded because there almost is none.
In all tests JSONKit was the clear winner or came pretty close to it. It really depends on the specifics of your own project whether you would best use this or Apple’s binary PLIST format. If you are coding multi-platform then it would probably be smarter to go for JSON because the binary PLIST format is not widely used on any other platforms than iOS or OSX. In contrast if you can afford the luxury of only targeting Apple platforms then binary PLIST is just as good a choice, provided you can install the components necessary on your server to be able to output it there.
For all other intents and purposes you can think of JSONKit and binary property lists as identical in transfer and processing speeds. Thanks to the amazing tuning that went into both.
Categories: Q&A
Binary plists de-duplicate strings. This can have a dramatic effect on read and write speed and file size.
An array of dictionaries, for example, each with the same four keys, will record those keys only once making the file much smaller, the read memory footprint smaller, and speeding up reading. The de-duplicating may make writing slower and use more memory while it is doing it, however.
You may already be using binary plists without trying. If you use XML plists in your app, they are automatically converted by binary plists when you build. It’s also a little surprising that when you open a binary plist with TextWrangler, it shows it as XML, and resaves it as binary. You pretty much have to dump the hex to be sure of what you are seeing.
It would be interesting to compare read and write memory footprints as well as speed.
The dictionary contained unique key/value pairs, therefore this bplist optimization should not affect the results.
Measuring the memory footprint sounds interesting, I will probably take a look at it soon.
Is there an easy way to record the memory footprint besides Instruments?
Instruments would be the way to go: HeapShot between repeated runs, maybe.
I tried TouchJSON for a project but found that it would not parse all correct JSON accurately, so moved to YAJL.
The JSONKit author posted stats on perfomance – https://github.com/johnezang/JSONKit
JSONKit is the best way as he thinks.
Do you have an example of JSON it would not parse properly? I was considering moving to TouchJSON because of speed but that has me a bit concerned.
I don’t have it any more (any it contained proprietary data so I couldn’t send it out anyway). However I do know that it contained lots of XML in its strings. The XML was confusing it into parsing everything from a certain point on as a single string.
So you considered moving to the library that was by far the slowest because of speed?
I think you might have misread the graphs.
JSONKit looks cool. Unfortunately, for the project I’m working on, I need to change that JSON into “real” model objects (not just NSDictionary objects). I’m using YAJL now… I set callbacks and know when new arrays/values/dictionaries are created, and create the appropriate objects as they come in. If JSON comes up with a way to allow for callbacks, I’d really like to take another look at it.
Please note that binary bplists allow for binary data to be transferred (which holds also true for the less known BSON format) while the other formats have no efficient representation for binary data (in our example, thumbnails images).
Just a historical note. The binary property list format is not the “old” format–it’s newer than the XML format. The old format was ASCII, and had a syntax similar to JSON. It used ‘{‘ and ‘}’ for dicts, ‘(‘ and ‘)’ for arrays (entries separated by commas), and “string” = “value” for dictionary entries (terminated by semi-colons).
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/PropertyLists/OldStylePlists/OldStylePLists.html#//apple_ref/doc/uid/20001012-BBCBDBJE
Apple switched to XML with Mac OS X.
I’ve been publishing since 2010 stats about the relative performance merits of JSON, YAML, XML, PLists, etc, with different XML parsers and JSON libraries. Here’s the result: https://github.com/akosma/iPhoneWebServicesClient and yes, JSONKit + Binary PLists are the way to go.