11
votes

Google protobuf is great protocol to serialize objects efficient, but it only supports serialization of trees, not graphs (lack of full Object Reference Tracking).

There are few implementation of Google idea in .NET. (i.e. protobuf-csharp-port, or protosharp), but most interesting is protobuf-net.

Protobuf-net is better because its architecture fits, to .NET world, and has several add-ins (not always compatible with original protobuf, but very useful).

One of that add-in is possibility to turn on reference tracking (AsReference option), which allows to serialize complex graphs even with cycles.

Unnecessary Protobuf-net v2 is in beta version, and AsReference option not works at real world scenarios. (without this option everything works well, but without Reference Tracikng protobuf-net is not able to serialize graphs and is not longer attractive serializer).

It still have some bugs:

So, I can't use this great tool, and I'm looking for alternative serializer which:

  • is at least as fast, and produces small output as protobuf
  • is easy to adopt to current project like protobuf-net
  • allows to serialize graph like DataContractSerializer with PreserveObjectReferences set to true
  • is stable not only for simple objects, but for complex real world scenarios
3
Of those; issue 232 is identical to SO 7219959 (i.e. not a problem - just a question, with an answer); SO 6294295 has a fine answer (i.e. not a problem - just a question, with an answer); the other 3 relate to mixing AsReference and inheritance (they are essentially duplicates). So it really comes down to: do you need those in combination! I would be intrigued to see your real-world scenarioMarc Gravell
SO 6294295 - I explained in comment, that protobuf-net not preserve List references, but only elements references. Real world scenario I described in Issue 242. I can't understand why references are only correctly preserved when object has no inheritors.Bartosz Pierzchlewicz
(lists) if that is your biggest barrier, I can support that scenario - it is simply a case of getting the time to do it (other demands on my time, etc). Is this the main problem?Marc Gravell
@Marc, do not take it personally, the Open Source tool and work you have done is great. But we talk about what protobuf-net is now, not what it could be in the future. Now protobuf-net not supports properly Reference Tracking, and could not be considered as a replacement for serializes which supports it. There is information at main project site: "I've also added a range of commonly requested features beyond the regular protobuf design, to help meet the every-day demands of .NET programmers (inheritance, reference-tracking, etc)." This is not true for current version. People should know..Bartosz Pierzchlewicz
I suggest to change information on project site to not mislead other users, and clearly say what protobuf-net v2 beta is, and what it can do now. Maybe you should say that some features are experimental now? It also should be clear information, that all performance test have been done without using these experimental features. I will be looking for new releases, and keep my fingers crossed. Please consider to allow other people to contribute project. It is worth it.Bartosz Pierzchlewicz

3 Answers

8
votes

Bartosz, while this question is quite old, I might recommend you and whoever stumbles upon it to use Migrant, available both from source and NuGet package. I'm one of the co-authors.

It can be easily adopted to even complicated scenarios, we tried to make it as easy to use as possible.

The output size is reasonably small. It depends on your object tree, of course, but it can be comparable with protobuf-net. Like protobuf, it uses Varint and ZigZag encoding.

Of course Migrant resolves the problems you've mentioned - It keeps the whole graphs of objects, handles inheritance, complex collections, version tolerance (up to some point) etc.

In terms of speed we try to be comparable with protobuf-net. It supports de/serialization using dynamically generated methods, which is much faster then classical reflection-based solutions.

Simple usage scenarios are available on the site I've linked to, but simple object cloning is straight-forward.

var myComplexObject = new MyComplexType(complexParameters);
var myObjectCopy = serializer.DeepClone(myComplexObject);

Writing to stream is as easy.

Of course, for very complicated types, there is a set of class decorators (attributes, hooks) to make things even smarter ;-)

2
votes

We are considering MessagePack. They claim to be 4x faster than ProtoBuf. However I don't know if it supports full object graphs. (we don't have that requirement, we actually flatten the objects we use for communication) In my scenario I would use it for communication between a .Net and a delphi layer (and that's also what's holding me back, no delphi support :) )

0
votes

It could be late to answer this specific question now but I'll post it here for someone who might seek for the same thing because reference tracking is still broken in protobuf-net.

You can use a fork: AqlaSerializer. It has much more improvements than just working reference tracking:

  • Nested collections
  • Multi-dimensional arrays
  • Very flexible and extendable mapping

and many others.

Disclaimer: I'm the author of it.