Monday, February 11, 2013

One of the cool things about working at KAYAK is hack week. One week out of the year employees take a break from their regular duties to work on a fun project of their choosing. It is a great opportunity to work on something different and with people you might not otherwise work with. At the end of the week each group presents a short video describing what they did.Last year I worked with Mike Bernardo, Ben Peebles-Mundy, and Stewart Ulm. We built Destinations - an iPhone app that lets you browse the vacation photos of your Facebook friends. It was a blast working with these guys on it. In just four days we had a working prototype and on the last day we produced an Apple-like commercial for it. I was super proud of the work we did on this one. Check out the video.

Wednesday, February 6, 2013

Core Data allows you to store a handful of primitive types (integers, decimals, strings, dates, etc..) but you can also store more complex objects by using the attribute type "transformable". Such objects are persisted by using a "transformer" to convert it to and from NSData (which is what actually gets stored).

Core Data's default transformer is based on archiving / NSKeyedArchiver and as my last post showed NSKeyedArchiver can be incredibly slow compared to other persistence techniques such as JSON-ifying.

Luckily Core Data allows you write custom transformers so you can use any technique you like to convert your objects to and from NSData. It is quite trivial then to write a simple transformer that converts between JSON using JSONKit.

#import "JSONTransformer.h"

#import "JSONKit.h"

@implementation JSONTransformer

+ (BOOL) allowsReverseTransformation {

returnYES;

}

+ (Class) transformedValueClass {

return [NSDataclass];

}

- (id) transformedValue:(id)value {

return [value JSONData];

}

- (id) reverseTransformedValue:(id)value {

return [value objectFromJSONData];

}

@end

If you are storing an NSDictionary or NSArray in Core Data I'd expect this transformer to give your app performance gains similar to those described in my last post over the default archiving transformer. Specifically for large data I'd expect you to see roughly:

3X reduction in storage size

3X read improvement

10-15X write improvement

Remember that for this to work your NSDictionary or NSArray must contain only simple objects that can be represented as JSON.

Monday, February 4, 2013

There are many ways to store data persistently in iOS. One common technique is to archive (serialize) objects using an NSArchiver. Archiving has always seemed slower than I expected and recently I began to wonder if it might be faster (or slower) to instead convert an object to JSON and write that out instead?

Tonight I ran a simple experiment to get a rough and unscientific approximation. You should consider this anecdotal.

The test was pretty straightforward. First I loaded up an NSDictionary with lots and lots of data and then measured the time it takes to write it and read it using both archiving and JSON-ifying. I also measured the size of the output files to see how they compare.

For archiving I simply used +[NSKeyedArchiver archiveRootObject:(id)rootObject toFile:(NSString *)path] and +[NSKeyedArchiver unarchiveObjectWithFile:(NSString *)path];

For JSON I used JSONKit and basic methods to read and write an NSString to and from a file.

The difference in the results was much larger than I expected. Using JSON was the clear winner in my tests. First it produced a file that was 3X smaller than the binary archive. Reading the data was about 3X faster too. The largest performance gain came from writing the data. Converting an object to JSON and writing it out was about 10-15X faster than using NSKeyedArchiver.

Below are the results on 4 different pieces of hardware (one of which was the iPhone simulator on a MBP).

The bottom line here is that if you are archiving "simple" objects (objects that can be easily represented as JSON, no cycles, etc...) you should strongly consider storing JSON instead of archiving.