Search code examples
compact-frameworkdeserializationprotocol-buffersprotobuf-net

Precompile protobuf-net Type Model for compact framework


I am deserializing thousands of objects on compact framework (3.5) and it is slow. Taking the devices 20+ seconds to finish. I found that it's done by reflection, instead of compile-and-run like non compact counterpart. So I thought, could I pre-compile and generate a type model dll first?

So I did the following:

  1. Extract all the Contract class to a smart device dll (it references Protobuf-net CF3.5 Dll)
  2. Create a desktop 3.5 console application, referencing Protobuf-net "Desktop" Dll and the Contract Dll created above.

    class Program
    {
      static void Main(string[] args)
      {
        var bb = TypeModel.Create();
    
        foreach (var t in Assembly.GetAssembly(typeof(My.ContractX)).GetTypes())
        {
            var contract = t.GetCustomAttributes(typeof (ProtoBuf.ProtoContractAttribute), false);
            if (contract.Length > 0)
            {
                bb.Add(t, true);
            }
        }
        bb.Compile("My.TypeModel", "My.Serialization.dll");
      }
    }
    
  3. Back to the device project, reference the Contract DLL, the generated My.Serialization.dll, and Protobuf-net CF3.5 Dll.
  4. Instead of using the default model, modified it to deserialize with the model constructed by "new TypeModel()"

It actually compiles correctly. I look at the generated dll in the Reflector, it's as expected.

Except that upon running, it throws MissingMethodException. However exactly what is missing is missing because compact framework doesn't report that.

My bet is because the generated My.Serialization.dll actually refers to the "Desktop" dll, but some method is missing.

So back to my question, how could I achieve type model pre-generation to be used in compact framework? Or could I get performance boost by doing something else?


Solution

  • Good news, I suspect. I've spent quite insane amounts of time working on the issue of cross-compilation (ok, I've been mainly driven by people asking about WP7 and WinRT), culminating in a brand new cross-platform precompiler.

    This already does what your code does, i.e. it looks for all the [ProtoContract] types in the input assembly/assemblies. I honestly haven't tried it for CF, but I'm very hopeful. I would genuinely love to hear how you get on. The only reason I haven't tested it against CF is that my external drive with my VS2008 VM died-a-death.

    Usage:

    precompile {some path}\YourCFDto.dll –o:MySerializer.dll –t:MySerializer
    

    Note: at the moment you would need to build "precompile" from source, but if this is an issue, I can get around to publishing it.

    If you have any problems whatsoever, please let me know.