views:

2083

answers:

7

Hi folks!

I want to use object serialization to communicate over the network between a mono server and Silverlight clients. It is pretty important that serialization is space efficient and pretty fast, as the server is going to host multiple real time games.

Any suggestions on what technique I should use? The BinaryFormatter adds a lot of overhead to serialized classes (Version, culture, class name, property names, etc) that is not required within this application.

What can I do to make this more space efficient? Thanks in advance!

Dennis

+4  A: 

You could pass the data through a DeflateStream or GZipStream to compress it prior to transmission. These classes live in the System.IO.Compression namespace.

Sean
Thanks! Do you know how bad this will impact on the de/serialization speed?
Dennis Kempin
In my experience they're not great for huge streams of data, but for most other cases the impact would be minor, but you'll need to try it and measure the time implications. It's only a few lines of code to add to the serialization calls, so easy to try out.
Sean
A: 

I think SOAP xml formatter is more efficient for your purpose.

Oysio
+13  A: 

You can use Protocol Buffers. I'm changing all my serialization code from BinaryFormatter with compression to Protocol Buffers and obtaining very good results. It's more efficient in both time and space.

There are two .NET implementations by Jon Skeet and Marc Gravell.

Jorge Villuendas
Thanks. These implementations also seem to work with silverlight!
Dennis Kempin
@Jorge - btw, did you realise that protobuf-net can hook directly into BinaryFormatter if you want to reduce the changes? You can implement ISerializable on your root objects, and just call into Serializer.Serialize/Serializer.Merge
Marc Gravell
@Jorge - out of curiosity, which framework did you go with? I won't be offended if the answer is "Jon's" - I'm just interested... I'm glad it is working for you, whichever it is.
Marc Gravell
@Marc - Yes, I know. My major changes are removing compression, it was adding too much processing work with little benefits. Thanks for your work!
Jorge Villuendas
@Marc - I'm using yours. It seems more flexible and better integrated with .NET framework.
Jorge Villuendas
+2  A: 

You could try using JSON. It's not as bandwidth efficient as protocol buffers but it would be a lot easier to monitor messages with tools like wireshark, which helps a lot when debugging problems. .net 3.5 comes with a json serializer.

Pablote
For wireshark: http://code.google.com/p/protobuf-wireshark/
Marc Gravell
+4  A: 

As the author, I would invite you to try protobuf-net; it ships with binaries for both mono 2.0 and silverlight 2.0, and is fast and efficient. If you have any problems whatsoever, just drop me an e-mail (see my stackoverflow profile); support is free.

Jon's version (see the earlier accepted answer) is also very good, but IMO the protobuf-net version is more idiomatic for C# - Jon's would be ideal if you were talking C# to java, so you could have a similar API at both ends.

Marc Gravell
I am already experimenting with protobuf-net, really great work, thanks a lot!
Dennis Kempin
Is adding the ProtoContract attribute to classes and ProtoMember attribute to the members necessary for using your library?
Binoj Antony
@Binoj - with "v1" (the current pre-compiled downloadable dll) "yes". However, "v2" fixes this (see http://marcgravell.blogspot.com/2010/02/protobuf-net-v2-on-iphone.html for full "v2" details). It isn't feature-complete yet (and to play with it you'd have to compile from the trunk), but the existing "v2" code works fine for a range of simple messages.
Marc Gravell
@Binoj - as a separate note; it doesn't *have* to be `ProtoContract` - it will also work with `[XmlType]+[XmlElement(Order=n)]` or `[DataContract]+[DataMember(Order=n)]`.
Marc Gravell
@Marc - Thanx for effort!
Binoj Antony
A: 

I had a very similar problem - saving to a file. But the following can also be used over a network as it was actually designed for remoting.

The solution is to use Simon Hewitt's library - see Optimizing Serialization in .NET - part 2.

Part 1 of the article states (the bold is my emphasis): "... If you've ever used .NET remoting for large amounts of data, you will have found that there are problems with scalability. For small amounts of data, it works well enough, but larger amounts take a lot of CPU and memory, generate massive amounts of data for transmission, and can fail with Out Of Memory exceptions. There is also a big problem with the time taken to actually perform the serialization - large amounts of data can make it unfeasible for use in apps ...."

I got a similar result for my particular application, 40 times faster saving and 20 times faster loading (from minutes to seconds). The size of the serialised data was also much reduced. I don't remember exactly, but it was at least 2-3 times.

It is quite easy to get started. However there is one gotcha: only use .NET serialisation for the very highest level datastructure (to get serialisation/deserialisation started) and then call the serialisation/deserialisation functions directly for the fields in the highest level datastructure. Otherwise there will not be any speed-up... For instance if a particular data structure (say Generic.List) is not supported by the library then .NET serialisation will used instead and this is a no-no. Instead serialise the list in client code (or similar). For an example see near "'This is our own encoding." in the same function as listed below.

For reference: code from my application - see near "Note: this is the only place where we use the built-in .NET ...".

Peter Mortensen
+2  A: 

I have some benchmarks for the leading .NET serializers available based on the Northwind dataset.

@marcgravell binary protobuf-net is the fastest implementations benchmarked that is about 7x faster than Microsoft fastest serializer available (the XML DataContractSerializer) in the BCL.

I also maintain some open-source high-performance .NET text serializers as well:

  • JSV TypeSerializer a compact, clean, JSON+CSV-like format that's 3.1x quicker than the DataContractSerializer
  • as well as a JsonSerializer that's 2.6x quicker.
mythz