Schnellster Weg zum Serialisieren und Deserialisieren von .NET-Objekten

86

Ich suche nach dem schnellsten Weg, um .NET-Objekte zu serialisieren und zu deserialisieren. Folgendes habe ich bisher:

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
quelle
2
Leistung oder Code-Footprint?
Ulrichb
Fragen Sie mich, ob ich Leistungsdaten oder Code benötige?
Aron
3
Er fragt, ob Sie mit "schnellstem Weg" die Leistung oder den Code-Footprint meinen. BinaryFormatterist in Bezug auf Code und Implementierung extrem schnell, aber eine Lösung wie die von Marc wird in einem Benchmark schneller abschneiden.
Cody Gray
ok, ich verstehe, ich meinte in Bezug auf die Leistung ...
Aron
Es gibt viele Links da draußen. Eines davon: blogs.msdn.com/b/youssefm/archive/2009/07/10/…
nawfal

Antworten:

57

Hier ist Ihr Modell (mit erfundenem CTund TE) unter Verwendung von Protobuf-Net (wobei die Verwendungsfähigkeit erhalten bleibtXmlSerializer , was nützlich sein kann - insbesondere für die Migration); Ich gebe demütig (mit vielen Beweise , wenn Sie es brauchen) , dass dies ist der schnellste (oder sicherlich einer der am schnellsten) Allzweck - Serializer in .NET.

Wenn Sie Zeichenfolgen benötigen, codieren Sie einfach die Binärdatei mit 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
quelle
2
G'day Marc, ich liebe die Arbeit mit den Protokollpuffern, die Sie geleistet haben, und ich weiß, dass dieser Beitrag fast 5 Jahre alt ist, aber der in einer Antwort hier zitierte Netserializer (Binoj) enthält Metriken, die anzeigen, dass Ihre Implementierung nicht die schnellste ist. Ist das eine faire Aussage / Werbung oder gibt es einen Kompromiss? danke
Jeremy Thompson
ok Ich sehe jetzt, NetSerialization funktioniert nur für die gleiche Version, wo ich nach Version Tolerant Serialization suche
Jeremy Thompson
1
Jeder, der denkt, dass dies schnell ist, muss etwas rauchen, es könnte für viele Fälle schnell genug sein und es könnte schneller sein als viele andere Serialisierungen da draußen, aber ist es tatsächlich schnell im Vergleich zum manuellen Parsen? Mein Gott nein.
BjarkeCK
@BjarkeCK-Serialisierer sind von Natur aus etwas komplizierter, da sie viele Dinge tun müssen, um zu verhindern, dass Leute ihre eigenen Füße abschießen (insbesondere, wenn sie Versionen iterieren). Die meisten Menschen möchten nicht ihr Leben damit verbringen, Serialisierungscode zu debuggen. Ein guter Serializer ist zwar zweifellos langsamer als eine perfekt implementierte
versionstolerante
1
@BjarkeCK Ich bin absolut anderer Meinung; Das ist für die meisten Leute nicht einmal im entferntesten nützlich. Was kommt als nächstes - jeden Tag unsere eigenen Sammlungen schreiben? Nein, es ist schwer , dieses Zeug auch nur einigermaßen gut zu machen . Sicher, wenn Sie tatsächlich die schnellste Ausgabe benötigen: Sie müssen sich die Hände schmutzig machen - aber für die meisten Menschen wäre dies eine wirklich schlechte Zeitverschwendung. Bestenfalls würde es viel länger dauern. Wahrscheinlicher wäre ihr Code fehlerhaft, unzuverlässig und wahrscheinlich langsamer als die Verwendung der verfügbaren Bibliotheken. Die meisten Leute sollten sich auf das konzentrieren, was ihre App braucht , nicht auf diese Details.
Marc Gravell
33

Ein comprehansive Vergleich zwischen diffreent Formaten von mir in diesem post- https://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/

Nur eine Probe aus der Post- Geben Sie hier die Bildbeschreibung ein

Maxime
quelle
5
Das ist keine Geschwindigkeit. Das ist Langsamkeit. In dem verlinkten Artikel heißt es "kleiner ist besser".
Timur Nuriyasov
2
@ TimurNuriyasov, das ist die Zeit, die für die Operation benötigt wurde
Maxim
2
Sie sagen also, Binär ist am langsamsten? Das glaube ich nicht! Ich denke, es bezieht sich richtig auf Geschwindigkeit, nicht auf Zeit.
Javid
2
Binär ist das langsamste. Versuchen Sie es selbst. Aber ich würde sagen, es ist am einfachsten, da es keine benutzerdefinierten Auflösungsaufgaben erfordert, um korrekt mit polymorphen Objekten (Schnittstellen usw.) zu arbeiten
Kamarey
1
@Kamarey schau dir meinen Test unten an ... Binär ist viel schneller als die anderen.
Jeremy Holovacs
19

Da ich daran interessiert war, beschloss ich, die vorgeschlagenen Methoden mit dem nächstgelegenen "Äpfel zu Äpfeln" -Test zu testen, den ich konnte. Ich habe eine Konsolen-App mit folgendem Code geschrieben:

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

Die Ergebnisse haben mich überrascht; Sie waren konsistent, wenn sie mehrmals ausgeführt wurden:

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.

Als ich diese Ergebnisse sammelte, entschied ich mich zu prüfen, ob ProtoBuf oder NetSerializer bei größeren Objekten besser abschneiden. Ich habe die Anzahl der Sammlungen auf 10.000 Objekte geändert, aber die Größe der Arrays auf 1-10.000 anstatt auf 1-100 erhöht. Die Ergebnisse schienen noch deutlicher:

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.

Mein Fazit lautet daher: Es kann Fälle geben, in denen ProtoBuf und NetSerializer gut geeignet sind, aber in Bezug auf die Rohleistung für zumindest relativ einfache Objekte ... BinaryFormatter ist um mindestens eine Größenordnung wesentlich leistungsfähiger.

YMMV.

Jeremy Holovacs
quelle
1
Vielleicht ist BinaryFormatter mit Arrays einfach sehr schnell.
Behrooz
4
Es ist möglich ... aber unter den genannten Bedingungen waren die Ergebnisse dramatisch. Die Lehre hier könnte sein, glauben Sie nicht, dass eine Methode unter allen Umständen die performanteste ist. Testen und Benchmarking leuchtet immer auf.
Jeremy Holovacs
In C ++ ist die Objektserialisierung etwa 100-mal schneller!
Mario M
Sehr interessant! Alle behaupteten, Protobuf sei der Schnellste, aber dies zeigt deutlich, dass es schmerzhaft langsam ist. Ich habe meinen BinaronSerializer zum Mix hier hinzugefügt. Dotnetfiddle.net/gOqQ7p - er ist fast doppelt so schnell wie BinaryFormatter, der mit Arrays bereits sehr schnell ist.
Zach Saw
16

Protobuf ist sehr sehr schnell.

Ausführliche Informationen zur Leistung dieses Systems und zu einer Implementierung finden Sie unter http://code.google.com/p/protobuf-net/wiki/Performance .

Pieter van Ginkel
quelle
Gibt es irgendwelche Nachteile bei der Verwendung von Protobuf?
Robert Jeppesen
11
Sie müssen Ihre Objekte mit Anmerkungen versehen. Protobuf speichert die Feldnamen und -typen nicht wie die Serializer, sondern übernimmt sie von Ihren tatsächlichen Typen. Dies ist einer der Gründe, warum die Zieldateien viel kleiner sind. Die Dokumentation erklärt dies alles. Ich benutze es schon seit einiger Zeit und wenn Sie eine schnelle (De-) Serialisierung und kleine Zieldateien benötigen, ist Protobuf wirklich der richtige Weg.
Pieter van Ginkel
Gibt es ein vollständiges Quellcodebeispiel mit Protobut in C #, um die Antwort zu ergänzen?
Kiquenet
Es ist nicht so schnell ... Tatsächlich ist es ziemlich langsam im Vergleich zu sehr, sehr, sehr schnellen Serialisierern: dotnetfiddle.net/gOqQ7p
Zach Saw
15

Ein weiterer Serializer, der behauptet, superschnell zu sein, ist der Netserializer .

Die auf ihrer Website angegebenen Daten zeigen eine Leistung von 2x gegenüber Protobuf. Ich habe dies nicht selbst versucht. Wenn Sie jedoch verschiedene Optionen prüfen, versuchen Sie dies ebenfalls

Binoj Antony
quelle
3
Ich habe gerade NetSerializer in meiner Anwendung ausprobiert und es wirkt Wunder. Es ist ein Versuch Wert.
Galen
netserializer eignet sich nicht zum Serialisieren von "Benutzer" -Objekten, bei denen die Bibliothek nicht weiß, mit welchen Typen sie beginnen sollen, oder hat sogar die Option, den Benutzer zu zwingen, ihre Objekte als serialisierbar zu markieren.
Zach Saw
6

Der in .net enthaltene binäre Serializer sollte schneller sein als der XmlSerializer. Oder ein anderer Serializer für protobuf, json, ...

Für einige von ihnen müssen Sie jedoch Attribute hinzufügen oder auf andere Weise Metadaten hinzufügen. Zum Beispiel verwendet ProtoBuf intern numerische Eigenschafts-IDs, und die Zuordnung muss durch einen anderen Mechanismus irgendwie erhalten bleiben. Die Versionierung ist mit keinem Serializer trivial.

CodesInChaos
quelle
Ja, es ist in der Tat sehr schnell und es behandelt viel mehr Fälle / Typen als das XML.
Leppie
1

Ich habe die Fehler im obigen Code entfernt und die folgenden Ergebnisse erzielt: Ich bin mir auch nicht sicher, wie NetSerializer erfordert, dass Sie die von Ihnen serialisierten Typen registrieren, welche Art von Kompatibilität oder Leistungsunterschieden möglicherweise auftreten können.

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.

Geänderter Code

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
quelle
1
Auf welche Fehler beziehen Sie sich?
Jeremy Holovacs
0

Sie können Salar.Bois versuchen Serializer der eine anständige Leistung hat. Der Fokus liegt auf der Nutzlastgröße, bietet aber auch eine gute Leistung.

Auf der Github-Seite gibt es Benchmarks, wenn Sie die Ergebnisse selbst sehen und vergleichen möchten.

https://github.com/salarcode/Bois

Salar
quelle
0

Ich habe mir erlaubt , Ihre Klassen in den CGbR-Generator einzuspeisen .Da es sich in einem frühen Stadium befindet, wird es noch nicht unterstützt DateTime, daher habe ich es einfach durch long ersetzt. Der generierte Serialisierungscode sieht folgendermaßen aus:

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

Ich habe eine Liste von Beispielobjekten wie folgt erstellt:

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

Ergebnisse auf meiner Maschine im ReleaseBuild:

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

Größe: 149000 Bytes

Zeit: 2,059 ms 3,13 ms

Bearbeiten: Ab CGbR 0.4.3 unterstützt der binäre Serializer DateTime. Leider ist die DateTime.ToBinaryMethode wahnsinnig langsam. Ich werde es bald durch etwas schnelleres ersetzen.

Edit2: Bei Verwendung von UTC DateTimedurch Aufrufen wird ToUniversalTime()die Leistung wiederhergestellt und mit 1,669 ms getaktet .

Toxantron
quelle