Testen von Serialisierern für .NET

Serbench-Code ist auf GitHub .

Projektstart


Dieses Benchmark-Projekt begann mit dem Artikel „ Serializers in .NET v.2 “ auf GeeksWithBlogs.net. In dem Artikel wurden eine ganze Reihe von für .NET verfügbaren Serialisierern berücksichtigt. Um diesen Artikel und den dazugehörigen Code in einen echten Benchmark zu verwandeln, mussten jedoch einige Verbesserungen vorgenommen werden.

Zunächst mussten Serialisierer an verschiedenen Datentypen getestet werden. Es gibt universelle Serializer und es gibt spezialisierte. Spezialisierte funktionieren sehr gut mit nur wenigen Datentypen, bei anderen Daten sind sie weitaus schlechter oder funktionieren überhaupt nicht. Wovon wir uns später überzeugt haben.

Zweitens unterscheiden sich Serialisierer stark in den Schnittstellen. Unser Benchmark sollte den Serialisierer nicht dazu zwingen, unserer Wahl der Schnittstelle zu folgen. Im Gegenteil, der Benchmark sollte so flexibel sein, dass jeder Serializer die für ihn am besten geeignete Schnittstelle verwenden kann. Das heißt, es müssen zusätzliche Parameter eines bestimmten Serializers an den Benchmark übertragen werden.

Der Autor eines der Serializer wandte sich mit dem Vorschlag, einen verbesserten Test durchzuführen, an den Autor des Artikels . Der Autor des Serializers war der Initiator dieses Projekts, er war auch der Hauptentwickler. Sergey war der Entwickler des gesamten Web-Teils des Projekts, all die tollen Berichte. Als Plattform für den Benchmark diente NFXDadurch war es möglich, alles Geplante (und vieles mehr) sehr schnell zu erledigen. NFX greift auf Hunderte solcher Artikel zurück, ich hoffe, er wird Sie auch interessieren.

Ergebnisse der Einreichungstests


Zunächst werde ich mich ein wenig auf die Präsentation der Ergebnisse konzentrieren, auf das, was besondere Aufmerksamkeit erfordert.

Schauen



wir uns als Beispiel die zusammenfassenden Informationen eines der Tests an: Links sehen wir drei Gewinner in den beiden wichtigsten Kategorien: Geschwindigkeit und Menge der serialisierten Daten. Ich muss sofort sagen, dass es mehr Gewinner geben kann, dass alle Serializer, die in die Kategorien Blau, Grün und in geringerem Maße Hellbraun fallen, als Gewinner gelten können. Die graue Kategorie sind Serializer, die diesen Test nicht bestehen.

In der Geschwindigkeitsspalte können Sie auf den Namen des Serializers klicken und eine Geschwindigkeitsentschlüsselung mit individuellen Nummern für die Serialisierung und Deserialisierung erhalten.

Die schlechteste Geschwindigkeit von Serialisierung und Deserialisierung wird als die Hauptgeschwindigkeit angenommen. Wir gehen davon aus, dass die Gesamtsystemleistung für Sie wichtig ist und nicht nur die Leistung der Serialisierung oder der Deserialisierung. Ihr Fall kann anders sein, daher wird die Geschwindigkeit einer anderen Operation auch mit einem dünnen Stab auf der Karte angegeben.

Worauf zu achten ist:

  • Für Serializer, die den Test nicht bestehen:

Bei einigen Tests haben die meisten Serializer, die wir getestet haben, Daten verloren. Wenn Sie sich für einen "schnellen" Serializer entscheiden, der Ihre Daten zerstört, ist dies das Schlimmste, was Sie sich vorstellen können. Sie werden viel Zeit damit verbringen, den Grund für die verzerrten Daten zu verstehen. Und Sie werden glücklich sein, wenn Sie in der Entwicklung und nicht in der Produktion darauf stoßen.

  • So gleichen Sie Ihre Daten mit Testdaten ab:

Unsere Empfehlung: Laden Sie den Benchmark-Code herunter, ändern Sie die Testdaten oder fügen Sie Ihre Daten hinzu und testen Sie sie erneut. Vertraue niemals deiner Intuition, vertraue keiner Extrapolation. Praktisch jeder Serializer fällt auf eine bestimmte Datengröße. Wir haben keine Limit-Tests durchgeführt, machen Sie es selbst für Ihre Daten. Nur sehr wenige Serializer haben alle unsere Tests bestanden.
Achtung!
Weiter im Text stoßen Sie ständig auf die Wörter "normalerweise", "öfter" usw. Ich entschuldige mich dafür und verstehe, dass dies die Testergebnisse etwas vage macht. Ich hoffe, dass Sie auch verstehen, dass die Testergebnisse uns nicht den besten Serializer zeigen sollten. Sie begrenzen nur die Gruppe von Serialisierern, die Sie als Basis benötigen. Sie werden einen Serializer für IHRE Daten verwenden. Daher muss die endgültige Entscheidung nach dem Ausführen von Tests für IHRE Daten getroffen werden, insbesondere wenn sich diese Daten stark von den Daten unterscheiden, die in unseren Tests verwendet wurden.
Was NICHT zu beachten ist:

  • Wenn die Tests den Unterschied in Zahlen mehrmals zeigen, achten Sie nicht auf den Unterschied in Prozent. Das ist nicht nur sinnlos, sondern auch falsch. Kleine Schwankungen der Geschwindigkeiten oder Größen können durch geringfügige Änderung der Testdaten leicht verzerrt werden.

Testdaten


Wir haben versucht, Daten für die am häufigsten verwendeten Anwendungen bereitzustellen. Wir haben keine Statistiken über die Verwendung von Serialisierern, daher haben wir Daten basierend auf unserer eigenen Erfahrung ausgewählt. Wenn Sie feststellen, dass wir etwas Wichtiges übersehen haben, teilen Sie uns dies mit oder fügen Sie einfach Ihre Testdaten zu Serbench hinzu.

Typische Anwendungen sehen wir in mehreren Bereichen:
  • verteilte, unabhängige Systeme . Programme arbeiten unabhängig voneinander, in unterschiedlichen Prozessen oder auf unterschiedlichen Maschinen und tauschen Daten aus. Programme tauschen nur Verträge, Schnittstellen aus. Dieser Typ umfasst Nachrichtensysteme .

Daten in Bezug auf diesen Typ: Typische Person, Telemetrie, EDI, Batching.

  • verteilte, aber stark verbundene Systeme . Der Unterschied zum vorherigen Fall besteht darin, dass Systeme nicht nur Verträge, sondern auch Bibliotheken austauschen können. Am häufigsten werden diese verwandten Systeme an einem Ort entworfen. RPC- Systeme (Remote Procedure Call) fallen unter diesen Typ .

Daten in Bezug auf diesen Typ: Typische Person, Stapelverarbeitung, Objektdiagramm.

  • Speichersysteme . Daten werden zwischen Programmen und Data Warehouses übertragen. Der Unterschied zu früheren Fällen besteht darin, dass der Serialisierungs- / Deserialisierungszyklus nicht innerhalb von Mikrosekunden oder Sekunden erfolgt. Daten können jahrelang gespeichert werden. Datenverträge ändern sich häufig während des Aufbewahrungszeitraums, was das Problem der Datenversionierung aufwirft. Wir haben Serializer nicht für die Arbeit mit Versionen getestet. Alle verfügbaren Testdaten können mit Speichersystemen verwendet werden. Serializer, die die Versionierung von Daten unterstützen, sind in diesem Fall möglicherweise praktischer.

Typische Person

Hier ist eine einfache Klasse ohne Schnittstellen und ohne Vererbung. Fast alle vorgestellten Serializer bestehen diesen Test.

Telemetrie

Ähnliche Daten werden von IoT-Geräten (Internet of Things) generiert. Ihr Unterschied besteht in der Verfügbarkeit von numerischen Informationen, Zeitstempeln und mehreren Kennungen. Manchmal sind die Daten sehr kurz, wenn eine oder mehrere Nummern gesendet werden. manchmal werden große Anordnungen von Zahlen gesendet. Die Datenstruktur ist einfach. Die Geschwindigkeit und Dichte des Datenpackens ist hier wichtig.

Edi

EDI-Daten (Electronic Data Interchange) entsprechen Dokumenten. Sie zeichnen sich durch eine komplexe hierarchische Struktur und Verschachtelung von Klassen aus. Es gibt Sammlungen von Klassen.



Objektgraph

Wenn Sie objektorientierte Entwicklung verwenden, mussten Sie sich wahrscheinlich mit ähnlichen Klassen befassen. Sie zeichnen sich durch komplexe Beziehungen zwischen Klassen aus. Wir testen die Konferenzklasse, die eine Sammlung von Ereignissen enthält. Eine Veranstaltung kann aus mehreren Teilnehmern und mehreren Konferenzthemen bestehen.

Interessanterweise kann ein Teilnehmer mehrere Beziehungen haben, von denen sich jede auf einen anderen Teilnehmer bezieht. Das Ergebnis sind zyklische Bindungen. Dies ist eine häufige Situation, aber es stellt sich heraus, dass nur sehr wenige Serializer mit zyklischen Verbindungen arbeiten können.



Batching

Stellen Sie sich eine Situation vor, in der Sie mehrere Instanzen von Objekten gleichzeitig senden müssen. Dies ist eine typische Situation in verteilten Systemen. Durch die Kombination mehrerer Datenelemente zu einem Paket, das in einem Schritt über das Netzwerk übertragen wird, können wir die Übertragung erheblich beschleunigen. Das Paket heißt Batch, daher der Name - Batching.

Normalerweise müssen wir ein Paket explizit erstellen, indem wir Datenelemente in einer speziellen Umschlagklasse verschachteln. Einige Serializer kommen ohne Umschläge aus, was die Entwicklung erheblich vereinfacht.

Testprozess


Hier ist alles einfach. In einem Testzyklus serialisieren wir ein Objekt oder mehrere Objekte im Falle eines Stapels und diserialisieren es sofort zurück. End- und Quellobjekte werden mit Ausblendungsfehlern verglichen. Der Vergleich ist nur für bestimmte Werte schnell. Wir führen keinen vollständigen Vergleich durch, aber alle Schnittstellen für einen vollständigen Vergleich sind verfügbar.

Mehrere Testzyklen werden zu einem Lauf zusammengefasst, zu dessen Beginn Testdaten generiert werden.

Mehrere Tests werden nacheinander kombiniert, wobei der erste Test ein Aufwärmtest ist. Dieser Test besteht normalerweise aus einem Zyklus, dessen Zweck darin besteht, alle für diesen Serialisierer benötigten Objekte zu initialisieren.

Einige Serializer werden schnell initialisiert, aber sie werden langsam serialisiert, andere umgekehrt. Wenn Sie den Serializer einmal verwenden müssen, sollten Sie die Ergebnisse von Aufwärmversuchen nicht vernachlässigen, für Sie sind sie die wichtigsten.

Normalerweise haben wir zuerst ein einzelnes Objekt und dann eine Sammlung von Objekten getestet. Wie sich herausstellte, können Serializer für die Arbeit mit Sammlungen optimiert werden. Dann können sie ihren Weg von Außenstehenden zu Führenden finden.

Alle Daten, in der Regel jedoch Sammlungen, können sehr groß sein, was zu einer starken Verlangsamung der Arbeit des Serialisierers oder zu Fehlern führen kann. In einigen unangenehmen Fällen hat der Serializer das System einfach aufgehängt.

Testergebnisse


Wir listen die Gewinner in den Tests auf, nur insgesamt für alle Tests. Die Gewinner der einzelnen Tests sind auf den Seiten mit den Testergebnissen auf der Website sehr gut vertreten . Hier ziehen wir einige Schlussfolgerungen. Ich richte Ihre Aufmerksamkeit auf die Tatsache, dass wir keinen Anspruch auf die endgültige Wahrheit erheben, sondern nur Zahlen kommentieren. Die Zahlen können sich bei zukünftigen Testupdates dramatisch ändern.

Typische Person

Die Testergebnisse .

Ich werde diesen Test im Detail betrachten. Der Rest der Tests ist im Grunde genommen.

Alle Tests

Fast alle Tests ergaben die gleichen schnellen Serializer: ProtoBuf, NFX Slim, MsgPack, NetSerializer. Aufwärmversuche ergaben einen sehr großen Geschwindigkeitsbereich. Microsoft BinaryFormatter zeigte eine gute Verpackung für Sammlungen und die schlechteste für eine Site. Leider hat Json.Net in keinem Test die Führung gebrochen.

Aufwärmversuche (Warmup)

Geschwindigkeit

Es gibt eine erstaunliche Variation der Geschwindigkeiten. NFX Slim führt Tausende von Operationen aus, und Jil beispielsweise nur eine Operation pro Sekunde. Der Großteil der Serialisierer führt ein oder zwei Dutzend Vorgänge pro Sekunde aus, manchmal mehrere Dutzend. Was noch überraschender ist, macht NFX Slim etwa 45.000! Deserialisierungen pro Sekunde. Aus offensichtlichen Gründen berücksichtigen wir jedoch nur den langsamsten Betrieb.

Verpackung

Die Spreizung ist nicht so groß wie bei Geschwindigkeiten. Mehrere Gewinner zeigen fast das gleiche Ergebnis und JSON-Serializer, die natürlich ähnliche Ergebnisse zeigen. Wir haben speziell zwei Tests für einen der JSON-Serializer (NFX Json) durchgeführt. Bei einem der Tests wird JSON-Text in einem ansprechenden Format mit allen Einrückungen und Zeilenvorschüben erstellt. Bei dem anderen Test wird JSON ohne Formatierung erstellt. Wie Sie sehen, sind die Größen für beide Fälle sehr unterschiedlich.

Dieses Ergebnis bestätigt erneut die bekannte Regel: Formatieren Sie niemals serialisierte Daten in einem Kanal! Formatieren Sie nur zur Präsentation und niemals zur Datenübertragung.

Batching

Die Testergebnisse .

Nur ProtoBuf, Microsoft BinaryFormatter und NFX Slim können die Serialisierung serialisieren. In diesem Slim gibt es einen speziellen Dosiermodus.

Es gibt große Geschwindigkeitsunterschiede für verschiedene Datentypen. Die Gewinner variieren von ProtoBuf für Trading- und EDI-Klassen bis hin zu Slim für RPC- und Personal-Klassen. Gleichzeitig konnte ProtoBuf die RPC-Klasse, in der das Feld object [] gefunden wurde, nicht serialisieren. Zusammenfassend lässt sich sagen, dass nur Microsoft BinaryFormatter und NFX Slim diesen Test erfolgreich bestanden haben. Microsoft BinaryFormatter zeigte wie immer hervorragende Ergebnisse in Aufwärmversuchen und durchweg schlechtere Ergebnisse in der Verpackung, was die fehlerfreie Funktion nicht beeinträchtigt.

Objektgraph

Die Testergebnisse .

Dieser Test erwies sich als der am schwierigsten zu serialisierende. Viele Serializer haben es nicht bestanden. Viele bestanden, zeigten aber gleichzeitig schreckliche Geschwindigkeiten und Verpackungen. Zum Beispiel Jil auf dem Test ObjectGraph: Conferences: 1; Teilnehmer: 250; Ereignisse: 10 packten die Daten in 2,6 MV, und die Führungskräfte packten die Daten in etwas mehr als 100 kW, das heißt, sie verbrauchten 26-mal weniger Speicher.

In diesem Test sehen wir einige Spitzenreiter, die mit sehr großem Abstand gewinnen. Dies sind ProtoBuf und NFX Slim. Microsoft BinaryFormatter ist in Bezug auf die Verpackung unerwartet unter diesen Marktführern aufgetaucht.

EDI X12

Die Testergebnisse .

Es war interessant, wie mit dem Anwachsen des Datenvolumens immer mehr Serialisierer mit Fehlern arbeiteten.

Wie beim Aufwärmtest üblich ist der Leader NFX Slim.

Es scheint, dass die führenden Hersteller von Verpackungen: ProtoBuf, MsgPack, NetSerializer, NFX Slim - für solche Fälle spezielle Verpackungsmethoden verwenden und diese Methoden sehr gut funktionieren.

Ich mache Sie auf die Tatsache aufmerksam, dass XML, das häufig für die Serialisierung und Verarbeitung von EDI-Dokumenten verwendet wird, in der Person von XmlSerializer ekelhafte Ergebnisse beim Packen zeigte und 8- bis 9-mal mehr Platz für serialisierte Daten beanspruchte.

Auswählen eines Serializers


Warum müssen wir einen Serializer wählen? Warum kommen wir mit Serialisierern aus dem .NET Framework nicht klar? (Microsoft bietet mehrere Serializer an, von denen einige kürzlich erschienen sind, z. B. Bond und Avro.)

Fakt ist, dass Serializer in verteilten Systemen immer wichtiger werden. Ein langsamer Serializer kann die maximale Leistung beeinträchtigen, ein schneller Serializer kann Ihr System besser machen als die Konkurrenz. Neue Serializer für .NET werden jetzt mit beneidenswerter Konsistenz angezeigt. Jeder von ihnen wird als der schnellste beworben. Als Beweis führen die Autoren Testergebnisse an.

Wir haben unser eigenes Testsystem entwickelt und eine unabhängige Studie durchgeführt. Nun werden die Kriterien besprochen, anhand derer Sie eine fundierte Auswahl des Serializers treffen können. Die Auswahlkriterien basieren auf den Testergebnissen.

Serialisierungszuverlässigkeit

Wir waren überrascht, dass viele Serializer die Elementartests nicht bestehen. Im besten Fall haben wir einen Fehler im Programm erhalten, im schlimmsten Fall gingen die Daten ohne Vorwarnung verloren oder Windows hing auf unbestimmte Zeit. Im Zwischenfall wurden Objekte verzerrt.

Lesen Sie die Ergebnisse unserer Tests sorgfältig durch. Diese Ergebnisse sind sehr datenabhängig. Wenn die Daten einfach strukturiert sind, kann fast jeder Serializer die Arbeit erledigen. Wenn die Daten komplex oder groß sind, ist leider nicht alles so gut.

Ich betone , auf Zuverlässigkeit, weil es an der Arbeit oder die Packungsdichte der Datenrate wird eine Entschuldigung für verlorene Daten oder ein blockiertes System unwahrscheinlich ist

wahrscheinlich der zuverlässigste Serializer ist Microsoft BinaryFormatter. Er ist nicht einer der schnellsten, aber es gibt einen wichtigen Grund dafür. Es serialisiert fast alles fehlerfrei.

Wählen Sie das Datenformat selbst aus?

Sie erhalten beispielsweise Daten von einem Partner im XML-Format und müssen mit XML arbeiten. Sie haben keine Möglichkeit, diese Situation zu ändern. In diesem Fall ist Ihre Auswahl auf XmlSerializer und Json.Net beschränkt.

Wenn Sie Ihr System in die Systeme anderer integrieren, wird die Wahl für Sie getroffen, und Sie müssen höchstwahrscheinlich eines von zwei Standardformaten verwenden: XML oder JSON. In seltenen Fällen müssen Sie mit dem CSV-Format oder mit dem Format eines bestimmten Systems arbeiten. Am häufigsten geschieht dies bei der Integration in Systeme aus dem vergangenen Jahrtausend.

Wenn Sie einfache .NET-Typen wie int, double, bool serialisieren müssen, ist die elementare Funktion ToString () für Sie ausreichend.

Serializer, die mit dem JSON-Format arbeiten, sind häufiger anzutreffen. JSON ist viel einfacher als XML, was in den meisten Fällen von Vorteil ist.

Viele Serializer packen Daten in ein eigenes Binärformat. Das JSON-Format ist normalerweise viel kompakter als XML. Binärformate sind normalerweise kompakter als JSON.

Wenn Sie das Datenformat selbst auswählen können, ist wahrscheinlich ein Binärformat die beste Wahl. Denken Sie jedoch daran, dass Sie in diesem Fall denselben Serializer für die Serialisierung und die Deserialisierung verwenden müssen. Momentan sind alle Binärformate eindeutig, keines davon ist standardisiert.

Datenpackungsdichte

Noch wichtiger: Geschwindigkeit der Serialisierung / Deserialisierung oder Packungsdichte der Daten?

Die Größe der serialisierten Daten ist normalerweise wichtiger als die Geschwindigkeit des Serialisierungs- / Deserialisierungsprozesses. Dies liegt an der Tatsache, dass die Prozessorgeschwindigkeit (die Geschwindigkeit, die die Serialisierung-Deserialisierung bestimmt) viel höher ist als die Datenrate im Netzwerk, die normalerweise in direktem Zusammenhang mit der Größe der übertragenen Daten steht. Eine Verringerung der Datengröße um 10% kann zu einer Erhöhung der Datenübertragung um 10% führen, und eine Verdoppelung der Geschwindigkeit der Serialisierung / Deserialisierung kann nur zu einer Erhöhung um 1% führen.

Versuchen Sie, die maximale Leistung Ihres Systems auszuschöpfen? Oder ist für Sie die Produktivität der Entwickler wichtiger?


Schauen Sie sich beispielsweise Serializer wie Bond, Thrift, Cap'n Proto an. Sie nehmen und serialisieren keine Klassen. Sie müssen eine spezielle IDL-Sprache verwenden und diese Klassen nicht beschreiben. In der Regel helfen Ihnen Dienstprogramme, die Klassenbeschreibungen aus den Klassen selbst generieren. Aber selbst wenn sie es sind, müssen Sie sich mit dieser Sprache auseinandersetzen, um die Zeit von der Entwicklung selbst abzubrechen.

Andere Serializer wie Slim von NFX erfordern nichts von Ihnen. Sie serialisieren einfach alle Klassen. In Zwischenfällen müssen serialisierbare Klassen mit Attributen versehen werden. Sie kennen wahrscheinlich das Attribut [Serializable].

Ist es wichtig Ja, das kann wichtig sein. Vor allem, wenn Ihre Klassen nicht trivial aufgebaut sind. In unserem Testsystem finden Sie beispielsweise eine EDI-Testklasse, die aus Dutzenden verschachtelter Klassen und Hunderten von Feldern besteht. Das Hinzufügen von Attributen zu all diesen Klassen und Feldern war mühsam und langwierig.

Dies ist auch wichtig, wenn Sie Klassen aus Bibliotheken serialisieren, auf deren Code Sie keinen Zugriff haben . Sie können den Code nicht nehmen und dort Attribute hinzufügen, der Code ist nicht verfügbar. Um diese Situation zu umgehen, verwenden Programmierer häufig das sogenannte DTO ( Data Transfer Object ). Ihre Verwendung ist mit Komplikationen des Programms und einem Rückgang der Entwicklungsgeschwindigkeit behaftet. Anstatt an Geschäftslogik zu arbeiten, müssen Sie Code schreiben, der nichts damit zu tun hat.

Wählen Sie Serializer für die Serialisierung und für die Deserialisierung oder nur für einen dieser Vorgänge?

Wenn Ihr System nur die empfangende oder sendende Partei ist, müssen Sie zustimmen, dass dies von dem Fall abweicht, in dem Sie für beide Vorgänge verantwortlich sind.

Haben Sie Sammlungen in Ihren Daten?

Serializer können für die Arbeit mit Objektgruppen optimiert werden. Andere Serializer unterscheiden Sammlungen in keiner Weise, sodass sie eine viel schlechtere Geschwindigkeit und Verpackung aufweisen.

Wie groß sind Ihre Daten?

Die Daten können sehr groß sein, was zu einer starken Verlangsamung des Serializers oder zu Serialisierungsfehlern führen kann. Ein Serializer kann das System einfach aufhängen.

Große Datenmengen im Speicher können sich auf die Speicherbereinigung auswirken, was wiederum zu langen Programmstopps führen kann.

Müssen Sie etwas sehr Außergewöhnliches serialisieren?

Und hier werden Sie von Serialisierern unterstützt, die genau auf diese Aufgabe spezialisiert sind. Zum Beispiel ein Serializer, der sich mit Linq-Ausdrücken befasst .

Benötigen Sie Super-Super-Leistung?

Dann ist es am besten, einen eigenen hochspezialisierten Serializer zu schreiben.

Wenn Sie dies nicht möchten, beachten Sie die zusätzlichen Methoden, die von verschiedenen Serialisierern verwendet werden. Batching zum Beispiel ist eine großartige Möglichkeit, die Geschwindigkeit zu erhöhen. Leider können es nur wenige Serializer ohne zusätzliche Codierung verwenden.

Parallele Serialisierung ist auch eine gute Methode, um hohe Geschwindigkeiten zu erzielen. Wenn Sie es verwenden, ist Ihnen die Thread-Sicherheit des Serializers wichtig .

Jetzt auch beliebt: