CMertens / protobuf-net

Automatically exported from code.google.com/p/protobuf-net
Other
0 stars 0 forks source link

List<T> serialization performance #425

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
We have just migrated to protobuf-net serialization and found a potential 
performance issue when serializing or deserializing a List<T>. Performance is 
as expected if the list is a property on a class, but if the List<T> is the top 
level object the performance reduces dramatically.

Here is a test which reproduces the issue:

    [ProtoContract]
    class Entity
    {
        [ProtoMember(1)]
        public string Foo { get; set; }
    }

    [Test]
    public void TestEmtpyBasicListOfEntity()
    {
        // Uncomment the below line to increase performance
        //RuntimeTypeModel.Default.Add(typeof(List<Entity>), true);

        var foos = new List<Entity> {new Entity {Foo = "foo"}};
        var memoryStream = new MemoryStream();
        Serializer.Serialize(memoryStream, foos);

        const int loop = 100000;
        var watch = Stopwatch.StartNew();
        for (var i = 0; i < loop; i++)
        {
            Serializer.Serialize(Stream.Null, foos);
        }

        Console.WriteLine("\tSerialized x{0} in {1}ms", loop,
                          watch.ElapsedMilliseconds);

        watch = Stopwatch.StartNew();
        for (var i = 0; i < loop; i++)
        {
            memoryStream.Position = 0;
            Serializer.Deserialize<List<Entity>>(memoryStream);
        }

        Console.WriteLine("\tDeserialized x{0} in {1}ms", loop,
                          watch.ElapsedMilliseconds);
    }

For comparisons sake, on my machine I get the following results:
Without adding to RuntimeTypeModel:
    Serialized x100000 in 9079ms
    Deserialized x100000 in 10541ms

With adding to RuntimeTypeModel:
    Serialized x100000 in 216ms
    Deserialized x100000 in 499ms

All done on version 2.0.0.668.

Is this intentional, or a bug? :)

Original issue reported on code.google.com by a...@martinthebird.com on 31 Dec 2013 at 8:00

GoogleCodeExporter commented 9 years ago
It is a known issue, certainly; basically, it can't currently skip as much 
stuff in this usage. The workaround, as you have discovered, is to use a root 
object. It is something I'd like to address, though.

Original comment by marc.gravell on 31 Dec 2013 at 3:54

GoogleCodeExporter commented 9 years ago
Thanks for the response Marc. We have opted to add our known types to the 
RuntimeTypeModel as it keeps our code cleaner.

Keep up the good work and happy new year!
adam

Original comment by a...@martinthebird.com on 2 Jan 2014 at 12:22