Dies für kleine Nutzlasten.
Ich möchte 1.000.000.000 pro 100ms erreichen.
Der Standard BinaryFormatter ist sehr langsam. Der DataContractSerializer ist langsamer als BinaryFormatter.
Protokollpuffer ( Ссылка ) scheinen langsamer als der BinaryFormatter für kleine Objekte zu sein!
Gibt es noch weitere Serialisierungsmechanismen, die sich entweder mit Hardcore-Coding oder Open-Source-Projekten befassen sollten?
BEARBEITEN: Ich serialisiere im Speicher und sende dann die Nutzdaten über TCP an einem asynchronen Socket. Die im Speicher generierten Payloads sind kleine Doppel-Arrays (10 bis 500 Punkte) mit einem ulong-Identifikator.
Ihre Leistungsanforderung beschränkt die verfügbaren Serializer auf 0. Ein benutzerdefinierter BinaryWriter und BinaryReader wären die schnellsten, die Sie erhalten könnten.
Ich hätte erwartet, dass das Protobuf-Netz sogar für kleine Objekte schneller ist ... aber vielleicht möchten Sie meinen Protokollpuffer ausprobieren Port auch. Ich habe den Port von Marc seit einiger Zeit nicht mehr benutzt - meiner war schneller, als ich das letzte Benchmarking gemacht habe, aber ich bin mir bewusst, dass er seither komplett überarbeitet wurde:)
Ich bezweifle, dass Sie erreichen werden, eine Milliarde Elemente in 100ms serialisieren, was auch immer Sie tun ... Ich denke, das ist einfach eine unvernünftige Erwartung, vor allem, wenn dies auf die Festplatte schreibt. (Wenn Sie das gleiche Bit Speicher wiederholt überschreiben, erhalten Sie eine viel bessere Leistung als das Serialisieren auf die Festplatte, aber ich bezweifle, dass Sie das wirklich versuchen.)
Wenn Sie uns mehr Kontext geben können, können wir vielleicht mehr helfen. Sind Sie in der Lage, die Ladung über mehrere Maschinen zu verteilen? (Die Serialisierung mehrerer Kerne auf dasselbe IO-Gerät ist wahrscheinlich nicht hilfreich, da ich nicht erwarte, dass dies eine CPU-gebundene Operation ist, wenn auf eine Festplatte oder das Netzwerk geschrieben wird.)
EDIT: Angenommen, jedes Objekt ist 10 doubles (je 8 Bytes) mit einem ulong-Bezeichner (4 Bytes). Das sind 84 Bytes pro Objekt bei minimum . Sie versuchen also, 8,4 GB in 100 ms zu serialisieren. Ich glaube wirklich nicht, dass das machbar ist, was auch immer du verwendest.
Ich führe jetzt meine Protokollpuffer-Benchmarks aus (sie geben pro Sekunde serialisierte Bytes an), aber ich bezweifle stark, dass sie dir geben werden, was du willst.
Sie behaupten, kleine Objekte seien langsamer als BinaryFormatter, aber jedes Mal, wenn ich es gemessen habe, habe ich das genaue Gegenteil gefunden, zum Beispiel:
Performance-Tests von Serialisierungen, die von WCF-Bindungen verwendet werden
Ich schließe, vor allem mit dem v2-Code, dass dies Ihre schnellste Option sein könnte. Wenn Sie Ihr spezifisches Benchmark-Szenario posten können, werde ich Ihnen gerne helfen zu sehen, was "up" ist ... Wenn Sie es hier nicht posten können, wenn Sie es mir direkt mailen möchten (siehe Profil), wäre das auch in Ordnung. Ich weiß nicht, ob deine angegebenen Zeiten unter irgendeinem Schema möglich sind, aber ich bin sehr sicher, dass ich dich viel schneller als alles, was du siehst, erreichen kannst.
Mit dem v2-Code liefert das CompileInPlace
das schnellste Ergebnis - es erlaubt einige IL-Tricks, die es nicht verwenden kann, wenn es zu einer physischen DLL kompiliert wird.
Der einzige Grund, Objekte zu serialisieren, besteht darin, sie mit einem generischen Transportmedium kompatibel zu machen. Netzwerk, Festplatte usw. Die Leistung des Serialisierers spielt keine Rolle, da das Transportmedium immer so viel langsamer ist als die rohe Leistung eines CPU-Kerns. Leicht um zwei Größenordnungen oder mehr.
Dies ist auch der Grund, dass Attribute einen akzeptablen Kompromiss darstellen. Sie sind auch I / O-gebunden, ihre Initialisierungsdaten müssen aus den Assembly-Metadaten gelesen werden. Das erfordert eine Festplatte zum ersten Mal lesen.
Wenn Sie also Perf-Anforderungen festlegen, müssen Sie sich zu 99% auf die Kapazität des Transportmediums konzentrieren. Eine Milliarde Nutzdaten in 100 Millisekunden erfordert sehr bullige Hardware. Angenommen, eine Nutzlast ist 16 Byte, müssen Sie 160 Gigabyte in einer Sekunde verschieben. Dies ist sogar jenseits der Speicherbusbandbreite innerhalb der Maschine. DDR RAM bewegt sich mit etwa 5 Gigabyte pro Sekunde. Eine 1-Gigabit-Ethernet-Netzwerkkarte bewegt sich mit 125 Megabyte pro Sekunde, Burst. Eine Massenfestplatte bewegt sich bei 65 Megabyte pro Sekunde und nimmt keine Suchanfragen an.
Ihr Ziel ist mit den aktuellen Hardwarefähigkeiten nicht realistisch.
Sie könnten eine benutzerdefinierte Serialisierung schreiben, indem Sie ISerailizable in Ihre Datenstrukturen implementieren. Auf jeden Fall werden Sie wahrscheinlich eine gewisse "Impedenz" von der Hardware selbst erwarten, um mit diesen Anforderungen zu serialisieren.
Nach meiner Erfahrung ist die Implementierung von Marc's Protokollpuffer sehr gut. Ich habe Jon nicht verwendet. Sie sollten jedoch versuchen, Techniken zu verwenden, um die Daten zu minimieren und nicht serialisieren die gesamte Menge.
Ich würde mir folgendes ansehen.
Wenn die Nachrichten klein sind, sollten Sie sich anschauen, welche Entropie Sie haben. Sie können Felder haben, die teilweise oder vollständig dedupliziert werden können. Wenn die Kommunikation nur zwischen zwei Parteien stattfindet, können Sie Vorteile beim Aufbau eines Wörterbuchs an beiden Enden erhalten.
Sie verwenden TCP, das einen Overhead hat, ohne dass eine Payload im Vordergrund steht. Sie sollten dies minimieren, indem Sie Ihre Nachrichten in größeren Paketen bündeln und / oder stattdessen UDP betrachten. Das Batching selbst, wenn es mit # 1 kombiniert wird, bringt Sie vielleicht näher an Ihre Anforderungen heran, wenn Sie Ihre gesamte Kommunikation mitteln.
Ist die volle Datenbreite doppelt erforderlich oder nur aus Bequemlichkeit? Wenn die zusätzlichen Bits nicht verwendet werden, ist dies eine Chance für die Optimierung bei der Umwandlung in einen binären Datenstrom.
Im Allgemeinen ist die generische Serialisierung ideal, wenn Sie mehrere Nachrichten haben, die Sie über eine einzelne Schnittstelle behandeln müssen, oder Sie kennen die vollständigen Implementierungsdetails nicht. In diesem Fall wäre es wahrscheinlich besser, eigene Serialisierungsmethoden zu erstellen, um eine einzelne Nachrichtenstruktur direkt in Byte-Arrays zu konvertieren. Da Sie die vollständige Implementierung kennen, wird die direkte Konvertierung kein Problem sein. Es würde auch sicherstellen, dass Sie den Code inline einbinden und Box / Unboxing so weit wie möglich verhindern können.
Dies ist der SCHNELLSTE Ansatz, den ich kenne. Es hat seine Nachteile. Wie eine Rakete, Sie würden es nicht auf Ihrem Auto wollen, aber es hat seinen Platz. So wie Sie Ihre Strukturen einrichten müssen und diese Struktur an beiden Enden Ihrer Pipe haben. Die Struktur muss eine feste Größe haben, oder es wird komplizierter als dieses Beispiel.
Hier ist die Perf, die ich auf meinem Rechner bekomme (i7 920, 12gb ram) Freigabemodus, ohne angehängtes Debugger. Es verwendet 100% CPU während des Tests, also ist dieser Test CPU gebunden.
%Vor%.. und der Code ...
%Vor%Wenn Sie sich nicht die Zeit nehmen möchten, einen umfassenden Mechanismus für die explizite Serialisierung / De-Serialisierung zu implementieren, versuchen Sie Folgendes: Ссылка ...
In meiner Verwendung mit großen Objekten (1GB + bei der Serialisierung auf Festplatte) finde ich, dass die von der NewtonSoft-Bibliothek erzeugte Datei 4,5 mal kleiner ist und 6 mal weniger Sekunden verarbeitet als bei Verwendung des BinaryFormatter.
Tags und Links .net c# serialization