La forma más rápida de serializar y deserializar objetos .NET

87

Estoy buscando la forma más rápida de serializar y deserializar objetos .NET. Esto es lo que tengo hasta ahora:

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
fuente
2
¿Rendimiento o huella de código?
ulrichb
¿Me está preguntando si necesito datos o código de rendimiento?
aron
3
Pregunta si, por "forma más rápida", te refieres en términos de rendimiento o en términos de huella de código. BinaryFormatteres extremadamente rápido en términos de código e implementación, pero una solución como la de Marc funcionará más rápido en un punto de referencia.
Cody Gray
ok, ya veo, quise decir en términos de rendimiento ...
aron
Hay muchos enlaces por ahí. Uno de ellos: blogs.msdn.com/b/youssefm/archive/2009/07/10/…
nawfal

Respuestas:

57

Aquí está su modelo (con inventado CTy TE) usando protobuf-net (pero conservando la capacidad de uso XmlSerializer, que puede ser útil, en particular para la migración); Humildemente presento (con mucha evidencia si la necesita) que este es el serializador de propósito general más rápido (o ciertamente uno de los más rápidos) en .NET.

Si necesita cadenas, simplemente codifique en base 64 el binario.

[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
fuente
2
Buen día, Marc, me encanta el trabajo de búferes de protocolo que has hecho y sé que esta publicación tiene casi 5 años, pero el netserializer citado en una respuesta aquí (Binoj) tiene métricas que indican que tu implementación no es la más rápida. ¿Es una declaración / publicidad justa o hay una compensación? gracias
Jeremy Thompson
ok, veo ahora, NetSerialization solo funciona para la misma versión en la que estoy buscando la serialización tolerante a la versión
Jeremy Thompson
1
Cualquiera que piense que esto es rápido debe estar fumando algo, podría ser lo suficientemente rápido para muchos casos, y podría ser más rápido que muchas otras serializaciones, pero ¿es realmente rápido, en comparación con analizarlo manualmente? Dios mío, no.
BjarkeCK
Los serializadores de @BjarkeCK son intrínsecamente un poco más complicados, ya que necesitan hacer muchas cosas para evitar que las personas se disparen (especialmente cuando iteran versiones); la mayoría de la gente no quiere pasar su vida depurar código de serialización, así: un buen serializador - aunque sin duda más lento que una aplicación manual de la versión intolerantes a la perfección en marcha - es por lo general un buen compromiso para la mayoría de la gente
Marc Gravell
1
@BjarkeCK Estoy totalmente en desacuerdo; eso no es ni remotamente útil para la mayoría de la gente. ¿Qué sigue, escribir nuestras propias colecciones todos los días? No: hacer estas cosas aunque sea razonablemente bien es difícil . Claro, si realmente necesita la salida más rápida: tendrá que ensuciarse las manos, pero para la mayoría de las personas, hacer esto sería una gran pérdida de tiempo. EN EL MEJOR , les tomaría mucho más tiempo. Lo más probable es que su código tenga errores, no sea confiable y probablemente sea más lento que usar las bibliotecas disponibles. La mayoría de la gente debería concentrarse en lo que necesita su aplicación , no en este minuto.
Marc Gravell
33

Una comparación completa entre los diferentes formatos realizados por mí en esta publicación: https://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/

Solo una muestra del post- ingrese la descripción de la imagen aquí

Máxima
fuente
5
Eso no es velocidad. Eso es lentitud. Dice "más pequeño es mejor" en el artículo vinculado.
Timur Nuriyasov
2
@TimurNuriyasov, ese es el tiempo que tomó hacer la operación
Maxim
2
¿Entonces dices que el binario es el más lento? ¡No lo creo! Supongo que se refiere correctamente a la velocidad, no al tiempo.
Javid
2
El binario ES el más lento. Pruébelo usted mismo. Pero diría que es más fácil, ya que no requiere ningún elemento de resolución personalizado para funcionar correctamente con objetos polimórficos (interfaces, etc.)
Kamarey
1
@Kamarey mira mi prueba a continuación ... el binario es mucho más rápido que los demás.
Jeremy Holovacs
19

Teniendo interés en esto, decidí probar los métodos sugeridos con la prueba de "manzanas a manzanas" más cercana que pude. Escribí una aplicación de consola, con el siguiente 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);
            }
        }
    }
}

Los resultados me sorprendieron; fueron consistentes cuando se ejecutaron varias veces:

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.

Al recopilar estos resultados, decidí ver si ProtoBuf o NetSerializer funcionaban mejor con objetos más grandes. Cambié el recuento de la colección a 10,000 objetos, pero aumenté el tamaño de las matrices a 1-10,000 en lugar de 1-100. Los resultados parecían aún más 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.

Mi conclusión, por lo tanto, es: puede haber casos en los que ProtoBuf y NetSerializer se adapten bien, pero en términos de rendimiento bruto para al menos objetos relativamente simples ... BinaryFormatter tiene un rendimiento significativamente mayor, al menos en un orden de magnitud.

YMMV.

Jeremy Holovacs
fuente
1
tal vez BinaryFormatter sea realmente rápido con matrices.
Behrooz
4
Es posible ... pero bajo las condiciones mencionadas, los resultados fueron dramáticos. La lección aquí podría ser: no crea que un método es el más eficaz en todas las circunstancias. Las pruebas y la evaluación comparativa siempre aclaran.
Jeremy Holovacs
En C ++, la serialización de objetos es unas 100 veces más rápida.
Mario M
¡Muy interesante! Todos afirmaron que el protobuf era el más rápido, pero esto muestra claramente que es dolorosamente lento. Agregué mi BinaronSerializer a la mezcla aquí dotnetfiddle.net/gOqQ7p : es casi el doble de rápido que BinaryFormatter, que ya es realmente rápido con matrices.
Zach Saw
16

Protobuf es muy, muy rápido.

Consulte http://code.google.com/p/protobuf-net/wiki/Performance para obtener información detallada sobre el rendimiento de este sistema y una implementación.

Pieter van Ginkel
fuente
¿Existe algún inconveniente en el uso de Protobuf?
Robert Jeppesen
11
Tienes que anotar tus objetos. Protobuf no almacena los nombres y tipos de campo como lo hacen los serializadores, sino que los toma de sus tipos reales. Esta es una de las razones por las que los archivos de destino son mucho más pequeños. La documentación explica todo esto. Lo he estado usando durante algún tiempo, y si necesita una (des) serialización rápida y archivos de destino pequeños, protobuf realmente es el camino a seguir.
Pieter van Ginkel
¿Alguna muestra de código fuente completo que use Protobut en C # para agregar a la respuesta?
Kiquenet
No es tan rápido ... De hecho, es bastante lento en comparación con los serializadores muy, muy, muy rápidos: dotnetfiddle.net/gOqQ7p
Zach Saw
@ZachSaw no es tan rápido si solo está tratando con matrices de números enteros (su ejemplo), pero muy pocas personas solo serializan números enteros. Ves los beneficios de velocidad (o al menos yo los veo), cuando comienzas a lidiar con tipos complejos anidados con muchos miembros.
matt.rothmeyer
15

Otro serializador que dice ser súper rápido es netserializer .

Los datos proporcionados en su sitio muestran un rendimiento de 2x - 4x sobre protobuf , no lo he probado yo mismo, pero si está evaluando varias opciones, intente esto también

Binoj Antony
fuente
3
Acabo de probar NetSerializer en mi aplicación y funciona de maravilla. Vale la pena intentarlo.
Galen
netserializer no es adecuado para serializar objetos de "usuario" donde la biblioteca no sabe cuáles son los tipos para empezar, o incluso tiene la opción de obligar al usuario a marcar sus objetos como serializables.
Zach Saw
6

El serializador binario incluido con .net debería ser más rápido que el XmlSerializer. U otro serializador para protobuf, json, ...

Pero para algunos de ellos necesita agregar atributos, o alguna otra forma de agregar metadatos. Por ejemplo, ProtoBuf usa ID de propiedad numéricos internamente, y el mapeo necesita ser conservado de alguna manera por un mecanismo diferente. El control de versiones no es trivial con ningún serializador.

CódigosInChaos
fuente
Sí, es realmente muy rápido y maneja muchos más casos / tipos que el Xml.
leppie
1

Eliminé los errores en el código anterior y obtuve los resultados a continuación: Además, no estoy seguro, dado que NetSerializer requiere que registre los tipos que está serializando, qué tipo de compatibilidad o diferencias de rendimiento podrían generar.

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
fuente
1
¿A qué errores te refieres?
Jeremy Holovacs
0

Puedes probar Salar.Bois serializador que tiene un rendimiento decente. Se centra en el tamaño de la carga útil, pero también ofrece un buen rendimiento.

Hay puntos de referencia en la página de Github si desea ver y comparar los resultados usted mismo.

https://github.com/salarcode/Bois

Salar
fuente
0

Me tomé la libertad de introducir tus clases en el generador CGbR .Debido a que está en una etapa temprana, no es compatible DateTime , así que simplemente lo reemplacé por long. El código de serialización generado se ve así:

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;
}

Creé una lista de objetos de muestra como este:

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 en mi máquina en Releaseconstrucción:

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

Tamaño: 149000 bytes

Hora: 2.059ms 3,13 ms

Editar: A partir de CGbR 0.4.3, el serializador binario admite DateTime. Desafortunadamente, el DateTime.ToBinarymétodo es increíblemente lento. Lo reemplazaré con algo más rápido pronto.

Edit2: cuando se usa UTC DateTimeal invocar, ToUniversalTime()el rendimiento se restaura y se registra en 1.669ms .

Toxantron
fuente