Efficiency Over Elegance
- September 24th, 2011
- By admin
- Write comment
What do you use when you want a server to communicate with a client over TCP? Some people would tell you to use HTTP. Some people would write their own binary protocol. A friend of mine is actively developing an IM client which communicates with a server using JSON. Unfortunately, some of this data needs to be raw binary, such as buddy icons, etc. Along with that, he uses JSON-framework for encoding and decoding.
JSON (JavaScript Object Notation), is a lightweight, human-readable way of representing dictionaries, arrays, strings, and numbers. For instance, a dictionary containing a single key might look something like this: ["myKey":999999]. You may immediately notice that the data could be smaller. There are two bytes already taken for the open and close brackets. Another two taken by the quotation marks. A few wasted bytes where a four-byte binary integer could be used to represent the number 999999. To some, this is fairly irrelevant. But consider the same amount of overhead for a very large amount of data. A more efficient binary storage method would be nice, and very handy to many.
I created a project called KeyedBits, a binary archive format. First I started off by writing a very simply Objective-C encoder and decoder that I called KBKit, which used some fancy object orientation to achieve its goal. Unfortunately, benchmarking this implementation gave unpromising results. Although it appears that KeyedBits saves an average of around 13%, KBKit was almost two times slower than JSON-framework. My natural reaction was not to optimize my Objective-C implementation, but to write another one in C.
I had already sacrificed the elegance and beauty of JSON, instead using a rather ugly binary format that only looks good when viewed in a hex editor. Now, I had to sacrifice the elegance of KBKit and instead write a C framework. For lack of a better name, I decided to call this C framework KBCKit.
It turns out that encoding was neck-and-neck between JSON-framework and KBKit. The real tie breaker was decoding. After I implemented both the encoder and decoder for KBCKit, and had written an Objective-C wrapper for each, I found that I was successful. KBCKit now is able to encode and decode almost twice as fast as JSON-framework. This, on top of the fact that there’s little overhead, makes KeyedBits a great alternative to JSON in Objective-C applications.
The lesson to be learned here is that sometimes beauty is not better than efficiency. Sure, my C implementation isn’t as fancy as my Objective-C implementation, but it certainly has a better end result. There are times when it’s okay to use a high-level language, but there are also times when it’s simply not appropriate. Imagine if the Linux kernel had been written in C++ instead of C. It would probably be a lot easier on the eyes, but ultimately easy on the eyes isn’t its purpose. Things like kernels, video decoders, and KBCKit were made to be used, not drawn on paper and hung in an art museum. The user doesn’t care how elegant the code is, they just want something with raw speed and power.