A maneira mais rápida de serializar e desserializar objetos .NET

87

Estou procurando a maneira mais rápida de serializar e desserializar objetos .NET. Aqui está o que tenho até agora:

public class TD
{
    public List<CT> CTs { get; set; }
    public List<TE> TEs { get; set; }
    public string Code { get; set; }
    public string Message { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }

    public static string Serialize(List<TD> tData)
    {
        var serializer = new XmlSerializer(typeof(List<TD>));

        TextWriter writer = new StringWriter();
        serializer.Serialize(writer, tData);

        return writer.ToString();
    }

    public static List<TD> Deserialize(string tData)
    {
        var serializer = new XmlSerializer(typeof(List<TD>));

        TextReader reader = new StringReader(tData);

        return (List<TD>)serializer.Deserialize(reader);
    }        
}
aron
fonte
2
Desempenho ou pegada de código?
ulrichb de
Você está me perguntando se eu preciso de dados ou código de desempenho?
aron de
3
Ele está perguntando se, por "caminho mais rápido", você quer dizer em termos de desempenho ou em termos de pegada de código. BinaryFormatteré extremamente rápido em termos de código e implementação, mas uma solução como a de Marc terá um desempenho mais rápido em um benchmark.
Cody Gray
ok, entendo, eu quis dizer em termos de desempenho ...
aron
Existem muitos links por aí. Um deles: blogs.msdn.com/b/youssefm/archive/2009/07/10/…
nawfal

Respostas:

57

Aqui está seu modelo (com inventado CTe TE) usando protobuf-net (ainda mantendo a capacidade de usar XmlSerializer, o que pode ser útil - em particular para migração); Apresento humildemente (com muitas evidências, se necessário) que este é o serializador de uso geral mais rápido (ou certamente um dos mais rápidos) em .NET.

Se você precisar de strings, apenas codifique o binário em base 64.

[XmlType]
public class CT {
    [XmlElement(Order = 1)]
    public int Foo { get; set; }
}
[XmlType]
public class TE {
    [XmlElement(Order = 1)]
    public int Bar { get; set; }
}
[XmlType]
public class TD {
    [XmlElement(Order=1)]
    public List<CT> CTs { get; set; }
    [XmlElement(Order=2)]
    public List<TE> TEs { get; set; }
    [XmlElement(Order = 3)]
    public string Code { get; set; }
    [XmlElement(Order = 4)]
    public string Message { get; set; }
    [XmlElement(Order = 5)]
    public DateTime StartDate { get; set; }
    [XmlElement(Order = 6)]
    public DateTime EndDate { get; set; }

    public static byte[] Serialize(List<TD> tData) {
        using (var ms = new MemoryStream()) {
            ProtoBuf.Serializer.Serialize(ms, tData);
            return ms.ToArray();
        }            
    }

    public static List<TD> Deserialize(byte[] tData) {
        using (var ms = new MemoryStream(tData)) {
            return ProtoBuf.Serializer.Deserialize<List<TD>>(ms);
        }
    }
}
Marc Gravell
fonte
2
Bom dia Marc, adorei o trabalho de buffers de protocolo que você fez e sei que este post já tem quase 5 anos, mas o netserializer citado em uma resposta aqui (Binoj) tem métricas indicando que sua implementação não é a mais rápida. Isso é uma declaração / anúncio justo ou há uma troca? obrigado
Jeremy Thompson,
ok vejo agora, NetSerialization só funciona para a mesma versão onde estou procurando Serialização Tolerante de Versão
Jeremy Thompson
1
Qualquer um que pensa que isso é rápido deve estar fumando algo, pode ser rápido o suficiente para muitos casos, e pode ser mais rápido do que muitos outros serializa por aí, mas é realmente rápido, em comparação com analisá-lo manualmente? Meu Deus não.
BjarkeCK 01 de
Os serializadores @BjarkeCK são inerentemente um pouco mais envolvidos, pois precisam fazer muitas coisas para evitar que as pessoas se precipitem (especialmente quando iteram versões); a maioria das pessoas não quer gastar suas vidas depurando código de serialização, então: um bom serializador - embora sem dúvida mais lento do que uma implementação manual intolerante a versão perfeitamente implementada - geralmente é um bom compromisso para a maioria das pessoas
Marc Gravell
1
@BjarkeCK discordo totalmente; isso não é nem remotamente útil para a maioria das pessoas. O que vem a seguir - escrever nossas próprias coleções todos os dias? Não: fazer essas coisas razoavelmente bem é difícil . Claro, se você realmente precisa a saída muito mais rápido: você vai ter que sujar as mãos - mas para a maioria das pessoas, fazer isso seria uma realmente ruim desperdício de seu tempo. NA MELHOR , eles levariam muito mais tempo. Mais provavelmente, seu código seria problemático, não confiável e provavelmente mais lento do que usar as bibliotecas disponíveis. A maioria das pessoas deve se concentrar no que seu aplicativo precisa , não nesses minutos.
Marc Gravell
33

Uma comparação abrangente entre formatos diferentes feitos por mim neste post- https://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/

Apenas uma amostra do pós insira a descrição da imagem aqui

Máxima
fonte
5
Isso não é velocidade. Isso é lentidão. Diz que "quanto menor, melhor" no link do artigo.
Timur Nuriyasov
2
@TimurNuriyasov, esse é o tempo que levou para fazer a operação
Maxim
2
Então você diz que binário é o mais lento? Acho que não! Acho que se refere corretamente à velocidade, não ao tempo.
Javid
2
O binário é o mais lento. Experimente você mesmo. Mas eu diria que é mais fácil, pois não requer qualquer coisa de resolução personalizada para funcionar corretamente com objetos polimórficos (interfaces, etc)
Kamarey
1
@Kamarey, olhe meu teste abaixo ... o binário é muito mais rápido que os outros.
Jeremy Holovacs 01 de
19

Tendo interesse nisso, decidi testar os métodos sugeridos com o teste "maçãs com maçãs" mais próximo que eu pudesse. Eu escrevi um aplicativo de console, com o seguinte código:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace SerializationTests
{
    class Program
    {
        static void Main(string[] args)
        {
            var count = 100000;
            var rnd = new Random(DateTime.UtcNow.GetHashCode());
            Console.WriteLine("Generating {0} arrays of data...", count);
            var arrays = new List<int[]>();
            for (int i = 0; i < count; i++)
            {
                var elements = rnd.Next(1, 100);
                var array = new int[elements];
                for (int j = 0; j < elements; j++)
                {
                    array[j] = rnd.Next();
                }   
                arrays.Add(array);
            }
            Console.WriteLine("Test data generated.");
            var stopWatch = new Stopwatch();

            Console.WriteLine("Testing BinarySerializer...");
            var binarySerializer = new BinarySerializer();
            var binarySerialized = new List<byte[]>();
            var binaryDeserialized = new List<int[]>();

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var array in arrays)
            {
                binarySerialized.Add(binarySerializer.Serialize(array));
            }
            stopWatch.Stop();
            Console.WriteLine("BinaryFormatter: Serializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var serialized in binarySerialized)
            {
                binaryDeserialized.Add(binarySerializer.Deserialize<int[]>(serialized));
            }
            stopWatch.Stop();
            Console.WriteLine("BinaryFormatter: Deserializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);


            Console.WriteLine();
            Console.WriteLine("Testing ProtoBuf serializer...");
            var protobufSerializer = new ProtoBufSerializer();
            var protobufSerialized = new List<byte[]>();
            var protobufDeserialized = new List<int[]>();

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var array in arrays)
            {
                protobufSerialized.Add(protobufSerializer.Serialize(array));
            }
            stopWatch.Stop();
            Console.WriteLine("ProtoBuf: Serializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var serialized in protobufSerialized)
            {
                protobufDeserialized.Add(protobufSerializer.Deserialize<int[]>(serialized));
            }
            stopWatch.Stop();
            Console.WriteLine("ProtoBuf: Deserializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            Console.WriteLine();
            Console.WriteLine("Testing NetSerializer serializer...");
            var netSerializerSerializer = new ProtoBufSerializer();
            var netSerializerSerialized = new List<byte[]>();
            var netSerializerDeserialized = new List<int[]>();

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var array in arrays)
            {
                netSerializerSerialized.Add(netSerializerSerializer.Serialize(array));
            }
            stopWatch.Stop();
            Console.WriteLine("NetSerializer: Serializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var serialized in netSerializerSerialized)
            {
                netSerializerDeserialized.Add(netSerializerSerializer.Deserialize<int[]>(serialized));
            }
            stopWatch.Stop();
            Console.WriteLine("NetSerializer: Deserializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            Console.WriteLine("Press any key to end.");
            Console.ReadKey();
        }

        public class BinarySerializer
        {
            private static readonly BinaryFormatter Formatter = new BinaryFormatter();

            public byte[] Serialize(object toSerialize)
            {
                using (var stream = new MemoryStream())
                {
                    Formatter.Serialize(stream, toSerialize);
                    return stream.ToArray();
                }
            }

            public T Deserialize<T>(byte[] serialized)
            {
                using (var stream = new MemoryStream(serialized))
                {
                    var result = (T)Formatter.Deserialize(stream);
                    return result;
                }
            }
        }

        public class ProtoBufSerializer
        {
            public byte[] Serialize(object toSerialize)
            {
                using (var stream = new MemoryStream())
                {
                    ProtoBuf.Serializer.Serialize(stream, toSerialize);
                    return stream.ToArray();
                }
            }

            public T Deserialize<T>(byte[] serialized)
            {
                using (var stream = new MemoryStream(serialized))
                {
                    var result = ProtoBuf.Serializer.Deserialize<T>(stream);
                    return result;
                }
            }
        }

        public class NetSerializer
        {
            private static readonly NetSerializer Serializer = new NetSerializer();
            public byte[] Serialize(object toSerialize)
            {
                return Serializer.Serialize(toSerialize);
            }

            public T Deserialize<T>(byte[] serialized)
            {
                return Serializer.Deserialize<T>(serialized);
            }
        }
    }
}

Os resultados me surpreenderam; eles eram consistentes quando executados várias vezes:

Generating 100000 arrays of data...
Test data generated.
Testing BinarySerializer...
BinaryFormatter: Serializing took 336.8392ms.
BinaryFormatter: Deserializing took 208.7527ms.

Testing ProtoBuf serializer...
ProtoBuf: Serializing took 2284.3827ms.
ProtoBuf: Deserializing took 2201.8072ms.

Testing NetSerializer serializer...
NetSerializer: Serializing took 2139.5424ms.
NetSerializer: Deserializing took 2113.7296ms.
Press any key to end.

Coletando esses resultados, decidi ver se o ProtoBuf ou o NetSerializer funcionava melhor com objetos maiores. Alterei a contagem da coleção para 10.000 objetos, mas aumentei o tamanho das matrizes para 1-10.000 em vez de 1-100. Os resultados pareceram ainda mais definitivos:

Generating 10000 arrays of data...
Test data generated.
Testing BinarySerializer...
BinaryFormatter: Serializing took 285.8356ms.
BinaryFormatter: Deserializing took 206.0906ms.

Testing ProtoBuf serializer...
ProtoBuf: Serializing took 10693.3848ms.
ProtoBuf: Deserializing took 5988.5993ms.

Testing NetSerializer serializer...
NetSerializer: Serializing took 9017.5785ms.
NetSerializer: Deserializing took 5978.7203ms.
Press any key to end.

Minha conclusão, portanto, é: pode haver casos em que ProtoBuf e NetSerializer são adequados, mas em termos de desempenho bruto para pelo menos objetos relativamente simples ... BinaryFormatter é significativamente mais performante, em pelo menos uma ordem de magnitude.

YMMV.

Jeremy Holovacs
fonte
1
talvez BinaryFormatter seja muito rápido com matrizes.
Behrooz
4
É possível ... mas nas condições mencionadas, os resultados foram dramáticos. A lição aqui pode ser apenas: não acredite que um método tenha o melhor desempenho em todas as circunstâncias. Teste e benchmarking sempre iluminam.
Jeremy Holovacs,
Em C ++, a serialização de objetos é cerca de 100 vezes mais rápida!
Mario M
Muito interessante! Todos afirmaram que o protobuf é o mais rápido, mas isso mostra claramente que é dolorosamente lento. Eu adicionei meu BinaronSerializer à mistura aqui dotnetfiddle.net/gOqQ7p - é quase duas vezes mais rápido que BinaryFormatter, que já é muito rápido com arrays.
Zach viu em
16

Protobuf é muito rápido.

Consulte http://code.google.com/p/protobuf-net/wiki/Performance para obter informações detalhadas sobre o desempenho deste sistema e uma implementação.

Pieter van Ginkel
fonte
Existe alguma desvantagem em usar Protobuf?
Robert Jeppesen de
11
Você tem que fazer anotações em seus objetos. Protobuf não armazena os nomes e tipos de campo como os serializadores fazem, mas os tira de seus tipos reais. Esse é um dos motivos pelos quais os arquivos de destino são muito menores. A documentação explica tudo isso. Eu já uso há algum tempo e se você precisa de uma (des) serialização rápida e de pequenos arquivos de destino, protobuf realmente é o caminho a seguir.
Pieter van Ginkel
Qualquer amostra de código-fonte completa usando Protobut em C # para adicionar à resposta?
Kiquenet
Não é tão rápido ... Na verdade, é muito lento em comparação com serializadores muito, muito, muito rápidos: dotnetfiddle.net/gOqQ7p
Zach viu
@ZachSaw não é tão rápido se você está lidando apenas com matrizes de inteiros (seu exemplo), mas muito poucas pessoas estão apenas serializando inteiros. Você vê os benefícios de velocidade (ou pelo menos eu vejo), quando você começa a lidar com tipos complexos aninhados com muitos membros.
matt.rothmeyer
15

Outro serializador que afirma ser super rápido é o netserializer .

Os dados fornecidos em seu site mostram desempenho de 2x - 4x sobre protobuf , eu não tentei fazer isso sozinho, mas se você está avaliando várias opções, experimente também

Binoj Antony
fonte
3
Acabei de experimentar o NetSerializer em meu aplicativo e ele faz maravilhas. Vale a pena tentar.
Galen
netserializer não é adequado para serializar objetos de "usuário" onde a biblioteca não sabe quais são os tipos para começar, ou mesmo tem a opção de forçar o usuário a marcar seus objetos como serializáveis.
Zach viu em
6

O serializador binário incluído com .net deve ser mais rápido que o XmlSerializer. Ou outro serializador para protobuf, json, ...

Mas, para alguns deles, você precisa adicionar atributos ou alguma outra forma de adicionar metadados. Por exemplo, ProtoBuf usa IDs de propriedade numéricos internamente e o mapeamento precisa ser conservado de alguma forma por um mecanismo diferente. O controle de versão não é trivial com nenhum serializador.

CodesInChaos
fonte
Sim, é muito rápido e lida com muito mais casos / tipos do que o Xml.
leppie de
1

Removi os bugs no código acima e obtive os resultados abaixo: Também não tenho certeza, dado como o NetSerializer exige que você registre os tipos que está serializando, que tipo de compatibilidade ou diferenças de desempenho isso poderia causar.

Generating 100000 arrays of data...
Test data generated.
Testing BinarySerializer...
BinaryFormatter: Serializing took 508.9773ms.
BinaryFormatter: Deserializing took 371.8499ms.

Testing ProtoBuf serializer...
ProtoBuf: Serializing took 3280.9185ms.
ProtoBuf: Deserializing took 3190.7899ms.

Testing NetSerializer serializer...
NetSerializer: Serializing took 427.1241ms.
NetSerializer: Deserializing took 78.954ms.
Press any key to end.

Código Modificado

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace SerializationTests
{
    class Program
    {
        static void Main(string[] args)
        {
            var count = 100000;
            var rnd = new Random((int)DateTime.UtcNow.Ticks & 0xFF);
            Console.WriteLine("Generating {0} arrays of data...", count);
            var arrays = new List<int[]>();
            for (int i = 0; i < count; i++)
            {
                var elements = rnd.Next(1, 100);
                var array = new int[elements];
                for (int j = 0; j < elements; j++)
                {
                    array[j] = rnd.Next();
                }
                arrays.Add(array);
            }
            Console.WriteLine("Test data generated.");
            var stopWatch = new Stopwatch();

            Console.WriteLine("Testing BinarySerializer...");
            var binarySerializer = new BinarySerializer();
            var binarySerialized = new List<byte[]>();
            var binaryDeserialized = new List<int[]>();

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var array in arrays)
            {
                binarySerialized.Add(binarySerializer.Serialize(array));
            }
            stopWatch.Stop();
            Console.WriteLine("BinaryFormatter: Serializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var serialized in binarySerialized)
            {
                binaryDeserialized.Add(binarySerializer.Deserialize<int[]>(serialized));
            }
            stopWatch.Stop();
            Console.WriteLine("BinaryFormatter: Deserializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);


            Console.WriteLine();
            Console.WriteLine("Testing ProtoBuf serializer...");
            var protobufSerializer = new ProtoBufSerializer();
            var protobufSerialized = new List<byte[]>();
            var protobufDeserialized = new List<int[]>();

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var array in arrays)
            {
                protobufSerialized.Add(protobufSerializer.Serialize(array));
            }
            stopWatch.Stop();
            Console.WriteLine("ProtoBuf: Serializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var serialized in protobufSerialized)
            {
                protobufDeserialized.Add(protobufSerializer.Deserialize<int[]>(serialized));
            }
            stopWatch.Stop();
            Console.WriteLine("ProtoBuf: Deserializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            Console.WriteLine();
            Console.WriteLine("Testing NetSerializer serializer...");
            var netSerializerSerialized = new List<byte[]>();
            var netSerializerDeserialized = new List<int[]>();

            stopWatch.Reset();
            stopWatch.Start();
            var netSerializerSerializer = new NS();
            foreach (var array in arrays)
            {
                netSerializerSerialized.Add(netSerializerSerializer.Serialize(array));
            }
            stopWatch.Stop();
            Console.WriteLine("NetSerializer: Serializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var serialized in netSerializerSerialized)
            {
                netSerializerDeserialized.Add(netSerializerSerializer.Deserialize<int[]>(serialized));
            }
            stopWatch.Stop();
            Console.WriteLine("NetSerializer: Deserializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            Console.WriteLine("Press any key to end.");
            Console.ReadKey();
        }

        public class BinarySerializer
        {
            private static readonly BinaryFormatter Formatter = new BinaryFormatter();

            public byte[] Serialize(object toSerialize)
            {
                using (var stream = new MemoryStream())
                {
                    Formatter.Serialize(stream, toSerialize);
                    return stream.ToArray();
                }
            }

            public T Deserialize<T>(byte[] serialized)
            {
                using (var stream = new MemoryStream(serialized))
                {
                    var result = (T)Formatter.Deserialize(stream);
                    return result;
                }
            }
        }

        public class ProtoBufSerializer
        {
            public byte[] Serialize(object toSerialize)
            {
                using (var stream = new MemoryStream())
                {
                    ProtoBuf.Serializer.Serialize(stream, toSerialize);
                    return stream.ToArray();
                }
            }

            public T Deserialize<T>(byte[] serialized)
            {
                using (var stream = new MemoryStream(serialized))
                {
                    var result = ProtoBuf.Serializer.Deserialize<T>(stream);
                    return result;
                }
            }
        }

        public class NS
        {
            NetSerializer.Serializer Serializer = new NetSerializer.Serializer(new Type[] { typeof(int), typeof(int[]) });

            public byte[] Serialize(object toSerialize)
            {
                using (var stream = new MemoryStream())
                {
                    Serializer.Serialize(stream, toSerialize);
                    return stream.ToArray();
                }
            }

            public T Deserialize<T>(byte[] serialized)
            {
                using (var stream = new MemoryStream(serialized))
                {
                    Serializer.Deserialize(stream, out var result);
                    return (T)result;
                }
            }
        }
    }
}
John Heilman
fonte
1
A quais bugs você está se referindo?
Jeremy Holovacs
0

Você pode tentar o serializador Salar.Bois, que tem um desempenho decente. Seu foco está no tamanho da carga útil, mas também oferece bom desempenho.

Existem benchmarks na página do Github se você deseja ver e comparar os resultados por si mesmo.

https://github.com/salarcode/Bois

Salar
fonte
0

Tomei a liberdade de alimentar suas aulas no gerador CGbR .Por estar em um estágio inicial, ele ainda não é compatível DateTime, então simplesmente substituí-o por longo. O código de serialização gerado é semelhante a este:

public int Size
{
    get 
    { 
        var size = 24;
        // Add size for collections and strings
        size += Cts == null ? 0 : Cts.Count * 4;
        size += Tes == null ? 0 : Tes.Count * 4;
        size += Code == null ? 0 : Code.Length;
        size += Message == null ? 0 : Message.Length;

        return size;              
    }
}

public byte[] ToBytes(byte[] bytes, ref int index)
{
    if (index + Size > bytes.Length)
        throw new ArgumentOutOfRangeException("index", "Object does not fit in array");

    // Convert Cts
    // Two bytes length information for each dimension
    GeneratorByteConverter.Include((ushort)(Cts == null ? 0 : Cts.Count), bytes, ref index);
    if (Cts != null)
    {
        for(var i = 0; i < Cts.Count; i++)
        {
            var value = Cts[i];
            value.ToBytes(bytes, ref index);
        }
    }
    // Convert Tes
    // Two bytes length information for each dimension
    GeneratorByteConverter.Include((ushort)(Tes == null ? 0 : Tes.Count), bytes, ref index);
    if (Tes != null)
    {
        for(var i = 0; i < Tes.Count; i++)
        {
            var value = Tes[i];
            value.ToBytes(bytes, ref index);
        }
    }
    // Convert Code
    GeneratorByteConverter.Include(Code, bytes, ref index);
    // Convert Message
    GeneratorByteConverter.Include(Message, bytes, ref index);
    // Convert StartDate
    GeneratorByteConverter.Include(StartDate.ToBinary(), bytes, ref index);
    // Convert EndDate
    GeneratorByteConverter.Include(EndDate.ToBinary(), bytes, ref index);
    return bytes;
}

public Td FromBytes(byte[] bytes, ref int index)
{
    // Read Cts
    var ctsLength = GeneratorByteConverter.ToUInt16(bytes, ref index);
    var tempCts = new List<Ct>(ctsLength);
    for (var i = 0; i < ctsLength; i++)
    {
        var value = new Ct().FromBytes(bytes, ref index);
        tempCts.Add(value);
    }
    Cts = tempCts;
    // Read Tes
    var tesLength = GeneratorByteConverter.ToUInt16(bytes, ref index);
    var tempTes = new List<Te>(tesLength);
    for (var i = 0; i < tesLength; i++)
    {
        var value = new Te().FromBytes(bytes, ref index);
        tempTes.Add(value);
    }
    Tes = tempTes;
    // Read Code
    Code = GeneratorByteConverter.GetString(bytes, ref index);
    // Read Message
    Message = GeneratorByteConverter.GetString(bytes, ref index);
    // Read StartDate
    StartDate = DateTime.FromBinary(GeneratorByteConverter.ToInt64(bytes, ref index));
    // Read EndDate
    EndDate = DateTime.FromBinary(GeneratorByteConverter.ToInt64(bytes, ref index));

    return this;
}

Criei uma lista de objetos de amostra como esta:

var objects = new List<Td>();
for (int i = 0; i < 1000; i++)
{
    var obj = new Td
    {
        Message = "Hello my friend",
        Code = "Some code that can be put here",
        StartDate = DateTime.Now.AddDays(-7),
        EndDate = DateTime.Now.AddDays(2),
        Cts = new List<Ct>(),
        Tes = new List<Te>()
    };
    for (int j = 0; j < 10; j++)
    {
        obj.Cts.Add(new Ct { Foo = i * j });
        obj.Tes.Add(new Te { Bar = i + j });
    }
    objects.Add(obj);
}

Resultados na minha máquina na Releaseconstrução:

var watch = new Stopwatch();
watch.Start();
var bytes = BinarySerializer.SerializeMany(objects);
watch.Stop();

Tamanho: 149000 bytes

Tempo: 2.059ms 3,13ms

Edit: Começando com CGbR 0.4.3, o serializador binário oferece suporte a DateTime. Infelizmente, o DateTime.ToBinarymétodo é incrivelmente lento. Vou substituí-lo por algo mais rápido em breve.

Edit2: Ao usar UTC DateTimeinvocando, ToUniversalTime()o desempenho é restaurado e o clock é de 1.669ms .

Toxantron
fonte