2009-11-12 4 views
33

Ich möchte verstehen, warum the protocol buffers solution for .NET entwickelt von Marc Gravell ist so schnell wie es ist.Wie erreicht protobuf-net eine respektable Leistung?

Ich kann verstehen, wie die ursprüngliche Google-Lösung ihre Leistung erreichte: Sie generiert voroptimierten Code für die Objektserialisierung; Ich habe etwas Serialisierung von Hand geschrieben und weiß, dass es möglich ist, ziemlich schnellen Code auf diese Weise zu schreiben, wenn Sie die Reflexion vermeiden. Die Bibliothek von Marc ist eine Runtime-Lösung, die Attribute verwendet und keinen generierten Code erzeugt. Wie funktioniert es?

+4

Haben Sie versucht, die Quelle zu lesen? Oder Mark direkt fragen? – Lazarus

+0

Ich habe versucht und sogar einige Ideen, aber wenn jemand eine schnelle Antwort geben kann, wäre es schön – MichaelT

+2

Ich werde gerne stundenlang darüber reden ;-p Aber es wird warten müssen, bis ich die Arbeit fertig habe ... –

Antwort

41

protobuf-net verwendet ein Strategie-Pattern; Nach Bedarf (einmal pro Typ) verwendet es Reflektion, um die Typen zu betrachten, und erstellt eine Reihe von Serialisierern (basierend auf einer gemeinsamen Schnittstelle), die es zum Serialisieren und Deserialisieren verwenden kann - also wenn es in Verwendung ist es gerade durchläuft der bekannte Satz von Serialisierern.

Inside das, es versucht, Reflexion sinnvoll zu verwenden, wenn man mit Mitgliedern spricht; es verwendet Delegate.CreateDelegate, um mit Eigenschaften zu sprechen, und DynamicMethod (und benutzerdefinierte IL), um mit Feldern zu sprechen (wenn möglich; es hängt vom Zielframework ab). Dies bedeutet, dass es immer mit bekannten Delegatentypen spricht, anstatt nur DynamicInvoke (was sehr langsam ist).

Ohne verrückt werden, hat der Code einige Optimierungen hat (wohl auf Kosten der Lesbarkeit) in Bezug auf:

  • lokaler byte[] Pufferung (des Ein-/Ausgabe-Streams)
  • feste Größe mit Arrays (anstatt Listen usw.); vielleicht zu viel
  • Generika mit Boxen zu vermeiden
  • zahlreiche Optimierungen/Rotationsdaten/etc um die binäre Verarbeitung Schleifen

Im Nachhinein denke ich, dass ich einen Fehler auf dem Generika-Punkt gemacht; die Komplexität bedeutete, dass Generika in das System bent it out of shape in a few places gezwungen werden, und verursacht aktiv einige große Probleme (für komplexe Modelle) on compact framework.

Ich habe einige Entwürfe (in meinem Kopf nur) diese nicht Generischer Schnittstellen Refactoring, und stattdessen (für geeignete Rahmenbedingungen) mehr Einsatz von ILGenerator (meine erste Wahl Expression gewesen wäre, aber dass Kräfte eine höhere Framework-Version). Das Problem ist jedoch, dass dies viel Zeit in Anspruch nehmen wird, und bis vor kurzem I've been pretty swamped.

Kürzlich habe ich es geschafft, start spending some time on protobuf-net again, so hoffentlich werde ich meinen Rückstand von Anfragen usw. löschen und damit bald beginnen. Es ist auch meine Absicht, es mit Modellen anderen als Reflexion (das Beschreiben der Drahtabbildung getrennt zu arbeiten) zu bekommen.


und erzeugt keine generierten Code

ich auch, dass es zwei (optional), wenn Sie CODEGEN Routen generierten Code verwenden soll klären sollte; protogen.exe oder VS add-in ermöglichen die Codegenerierung aus einer .proto-Datei.Aber das ist nicht benötigt - es ist vor allem nützlich, wenn Sie eine bestehende .proto-Datei haben, oder beabsichtigen, mit einer anderen Sprache (C++ etc) für die Vertragsentwicklung zu interagieren.

-3

Seine Leistung ist sehr gut!

Sie können einen umfassenden Vergleich zwischen verschiedenen Formaten, darunter protobuf durch me- http://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/

Dieser Vergleich beinhaltet große und kleine Datenproben und verschiedene Formate durchgeführt sehen.

Einer der Tests in meiner Post enter image description here

+0

Die Frage war, wie die Leistung erreicht wurde, nicht wie leistungsfähig es ist. –