Serialization for Silverlight Web services: SilverlightSerializer and protobuf-net with QuickLZSharp compression

Introduction
SilverlightSerializer 2.0 and protobuf-net offer substantial improvements on the default binary serialization done by WCF. They can be used to create byte arrays for the objects being serialized in a service consumed by Silverlight. Protobuf-net is a .NET implementation of protocol buffers. protocol buffers is name of the binary serialization format used by Google, and is known to be very fast and efficient. Protobuf-net is compatible with most of the .NET family of frameworks. SilverlightSerializer is a less well-known binary serializer which was developed specifically for Silverlight. It is particularly simple to use.

I adapted a project using SilverlightSerializer to use protobuf-net. Protobuf-net offered improved reduction in the size of WCF messages, but I observed that there seemed to be a smaller difference in the message sizes with larger objects than with small ones. I decided to test how the two compared in serializing (relatively) large objects.

I also investigated the benefits of using QuickLZSharp compression on Protobuf-net serialized byte arrays. Compressing SilverlightSerializer byte arrays with QuickLZ has already been shown to be highly beneficial. For protobuf-net serialized arrays, it offered a small benefit in most cases, and a very great benefit where the serialized data consisted of duplicate strings.

Tests
The default WCF binding (basicHttpBinding) was used for all tests, which means the envelope was not encoded into binary. If binaryMessageEncoding was used then all results would be smaller (and the relative difference between the two slightly greater). Duplicate method names were used for all tests so that the envelope size would be the same in all cases.

For protobuf-net results, brackets indicate the byte array was compressed with QuickLZSharp. All SilverlightSerializer results have the compression applied. A List object was used to hold the data in all cases.

10,000 doubles (1-10000):
SS: 43,928
PB: 32,152 bytes (31,250 bytes)

10,000 strings (“1” – “10000”):
SS: 41,228 bytes
PB: (30,668 bytes)

10,000 strings (all “Hello world”):
SS: 2,760 bytes
PB: 2,137 bytes (594 bytes)

1000,000 strings (“1” – “100000”):
SS: 404,580 bytes
PB: 320,459 bytes (294,408 bytes)

Conclusions
For all tests, protobuf-net consistently resulted in messages at most 73% the size of equivalent compressed SilverlightSerializer messages. I’ve observed that there seems to be a greater reduction with objects smaller than those in the tests described above (approx. 65% based on casual observation).

QuickLZSharp compression consistently improved the message size with both. When applied to protobuf-net serialized data, the level of improvement corresponded with the level of duplication within the data being sent. In a separate project I measured the time it took to apply QuickLZSharp compression to an arbitrary object that was 3,764B before compression. It took 1 ms, and the size was reduced to 3364B. I would suggest that compression is generally worth doing, given the possible improvements. If bandwidth reduction is a priority in a Silverlight Web service then it is worth using compressed protobuf-net serialized byte arrays.