Hat jemand, der Erfahrung mit diesen Bibliotheken hat, irgendeinen Kommentar, welchen sie bevorzugen? Gab es Leistungsunterschiede oder Schwierigkeiten bei der Verwendung?
Ich habe ein bisschen mit beiden Systemen herumgespielt, nichts Ernstes, nur ein paar einfache Hacksachen, aber ich hatte das Gefühl, dass es einen Unterschied gibt, wie man die Bibliotheken verwenden soll.
Mit boost :: serialization schreiben Sie zuerst Ihre eigenen Strukturen/Klassen und fügen dann die Archivierungsmethoden hinzu. Es bleiben jedoch einige ziemlich "schlanke" Klassen übrig, die als vererbte Datenelemente verwendet werden können.
Bei Protokollpuffern ist die Menge des für eine einfache Struktur generierten Codes ziemlich groß, und die generierten Strukturen und der Code sind eher für den Betrieb gedacht, und Sie verwenden die Funktionalität der Protokollpuffer, um Daten zu und von Ihren eigenen internen Strukturen zu transportieren .
Ich benutze Boost-Serialisierung schon lange und habe mich nur in Protokollpuffer eingegraben, und ich denke, sie haben nicht genau den gleichen Zweck. BS (hat das nicht kommen sehen) speichert Ihre C++ - Objekte in einem Stream, wohingegen PB ein Austauschformat ist, in das Sie lesen.
Das Datenmodell von PB ist viel einfacher: Sie erhalten alle Arten von Ints und Floats, Strings, Arrays und die grundlegende Struktur. Mit BS können Sie alle Ihre Objekte in einem Schritt direkt speichern.
Mit BS erhalten Sie also mehr Daten auf der Leitung, aber Sie müssen nicht alle Objektstrukturen neu erstellen, während Protokollpuffer kompakter sind, nach dem Lesen des Archivs jedoch noch mehr Arbeit zu erledigen ist. Wie der Name schon sagt, ist eines für Protokolle (sprachunabhängige, platzsparende Datenübergabe), das andere für die Serialisierung (unkomplizierte Speicherung von Objekten).
Was ist für Sie wichtiger: Geschwindigkeits-/Platzeffizienz oder sauberer Code?
Es gibt ein paar zusätzliche Bedenken bezüglich boost.serialization, die ich dem Mix hinzufügen möchte. Vorbehalt: Ich habe keine direkten Erfahrungen mit Protokollpuffern, außer mit dem Durchsuchen der Dokumente.
Beachten Sie, dass, obwohl ich denke, dass boost und boost.serialization bei dem, was es tut, großartig ist, ich zu dem Schluss gekommen bin, dass die Standard-Archivformate, mit denen es kommt, keine gute Wahl für ein Drahtformat sind.
Es ist wichtig, zwischen den Versionen von Ihrer Klasse (wie in anderen Antworten erwähnt, dass boost.serialization etwas für die Versionierung von Daten unterstützt) und der Kompatibilität zwischen verschiedenen Versionen der Serialisierungsbibliothek zu unterscheiden.
Neuere Versionen von boost.serialization generiert möglicherweise keine Archive, die ältere Versionen deserialisieren können . (das Gegenteil trifft nicht zu: neuere Versionen dienen immer dazu, Archive älterer Versionen zu deserialisieren). Dies hat zu folgenden Problemen für uns geführt:
Google scheint tatsächlich das Protokollpuffer-Drahtformat zu veröffentlichen , und Wikipedia beschreibt sie als vorwärtskompatibel, abwärtskompatibel (obwohl ich denke, Wikipedia bezieht sich auf die Datenversionierung und nicht auf die Protokollpufferbibliothek) Versionierung). Obwohl keines davon eine Garantie für die Vorwärtskompatibilität darstellt, scheint es mir ein stärkeres Zeichen zu sein.
Zusammenfassend kann ich sagen, dass ich ein bekanntes, veröffentlichtes Wire-Format wie Protokollpuffer bevorzugen würde, wenn ich nicht in der Lage bin, Client und Server in Lockstep zu aktualisieren.
Fußnote: schamloser Plug für ein verwandte Antwort von mir.
Boost-Serialisierung
Protokollpuffer
Boost-Serialisierung ist eine Bibliothek zum Konvertieren eines Objekts in einen serialisierten Datenstrom. Protokollpuffer machen dasselbe, erledigen aber auch andere Aufgaben (wie Versionierung und Endian-Swapping). Boost-Serialisierung ist einfacher für "kleine einfache Aufgaben". Protokollpuffer sind wahrscheinlich besser für "größere Infrastruktur".
EDIT: 24-11-10: "automatisch" zur BS-Versionierung hinzugefügt.
Ich habe keine Erfahrung mit Boost-Serialisierung, aber ich habe Protokollpuffer verwendet. Ich mag Protokollpuffer sehr. Beachten Sie Folgendes (ich sage dies mit ohne Kenntnis von Boost).
Hoffe das hilft.
boost.serialization benötigt nur den C++ - Compiler und gibt Ihnen etwas Syntaxzucker
serialize_obj >> archive;
// ...
unserialize_obj << archive;
zum Speichern und Laden. Wenn nur C++ verwendet wird, sollten Sie boost.serialization eine ernsthafte Chance geben.
Ich habe mir kurz die Google-Protokollpuffer angesehen. Von dem, was ich sehe, würde ich sagen, dass es nicht direkt mit boost.serialization vergleichbar ist. Sie müssen der Toolchain einen Compiler für die .proto-Dateien hinzufügen und die .proto-Dateien selbst verwalten. Die API lässt sich nicht wie Boost.serialization in C++ integrieren.
boost.serialization erledigt seine Aufgabe sehr gut: zum Serialisieren von C++ - Objekten :) OTOH Eine Abfrage-API wie die Google-Protokollpuffer bietet Ihnen mehr Flexibilität.
Da ich bisher nur boost.serialization verwendet habe, kann ich den Leistungsvergleich nicht kommentieren.
Korrektur nach oben (denke mal, das ist diese Antwort ) über Boost Serialization:
Es erlaubt die Unterstützung von Datenversionierung .
Wenn Sie eine Komprimierung benötigen, verwenden Sie einen komprimierten Stream.
Kann Endian-Swapping zwischen Plattformen verarbeiten, da die Kodierung Text, Binär oder XML sein kann.
Ich habe nie etwas mit der Bibliothek von boost implementiert, aber ich fand die Protobuff von Google durchdachter und der Code ist viel sauberer und einfacher zu lesen. Ich würde vorschlagen, die verschiedenen Sprachen, mit denen Sie es verwenden möchten, anzusehen, den Code und die Dokumentation durchzulesen und sich zu entscheiden.
Die einzige Schwierigkeit, die ich mit Protobufs hatte, war, dass sie in ihrem generierten Code GetMessage () eine häufig verwendete Funktion benannten, die natürlich mit dem Win32-GetMessage-Makro in Konflikt steht.
Ich würde Protobufs trotzdem wärmstens empfehlen. Sie sind sehr nützlich.
Wie bei fast allem in der Technik lautet meine Antwort ... "es kommt darauf an."
Beide sind gut erprobte, geprüfte Technologien. Beide nehmen Ihre Daten in etwas freundliches auf, um sie irgendwo zu senden. Beide werden wahrscheinlich schnell genug sein, und wenn Sie wirklich ein Byte hier oder dort zählen, werden Sie wahrscheinlich mit keinem zufrieden sein (seien wir ehrlich, beide erstellten Pakete sind ein kleiner Bruchteil von XML oder JSON).
Für mich kommt es wirklich auf den Workflow an und ob Sie am anderen Ende etwas anderes als C++ benötigen.
Wenn Sie den Inhalt Ihrer Nachricht zuerst herausfinden möchten und ein System von Grund auf neu erstellen, verwenden Sie Protokollpuffer. Sie können sich die Nachricht abstrakt vorstellen und dann den Code automatisch in der gewünschten Sprache generieren (Plugins von Drittanbietern sind für fast alles verfügbar). Ich finde auch die Zusammenarbeit mit Protocol Buffers vereinfacht. Ich schicke einfach eine .proto-Datei und dann hat das andere Team eine klare Vorstellung davon, welche Daten übertragen werden. Ich lege ihnen auch nichts auf. Wenn sie Java verwenden wollen, machen Sie weiter!
Wenn ich bereits eine Klasse in C++ erstellt habe (und dies ist öfter passiert als nicht) und ich diese Daten jetzt über die Leitung senden möchte, ist die Boost-Serialisierung offensichtlich sehr sinnvoll (vor allem, wenn ich bereits an anderer Stelle eine Boost-Abhängigkeit habe.) ).
Ich weiß, dass dies jetzt eine ältere Frage ist, aber ich dachte, ich würde meine 2 Pence hineinwerfen!
Mit boost erhalten Sie die Möglichkeit, Daten in Ihre Klassen zu schreiben. Dies ist gut, weil die Datendefinition und die Gültigkeitsprüfung alle an einem Ort liegen.
Mit GPB können Sie am besten Kommentare in die .proto-Datei einfügen und hoffen, dass alle, die es verwenden, es lesen, darauf achten und die Gültigkeitsprüfungen selbst implementieren.
Es ist unnötig zu erwähnen, dass dies unwahrscheinlich und unzuverlässig ist, wenn Sie sich auf eine andere Person am anderen Ende eines Netzwerk-Streams verlassen, um dies mit derselben Kraft wie sich selbst zu tun. Wenn sich die Bedingungen für die Gültigkeit ändern, müssen außerdem mehrere Codeänderungen geplant, koordiniert und durchgeführt werden.
Ich halte GPB daher für ungeeignet für Entwicklungen, bei denen es wenig Gelegenheit gibt, regelmäßig mit allen Teammitgliedern zu sprechen und sich mit ihnen zu unterhalten.
== BEARBEITEN ==
Was ich damit meine, ist:
message Foo
{
int32 bearing = 1;
}
Nun, wer soll sagen, was der gültige Bereich von bearing
ist? Wir können haben
message Foo
{
int32 bearing = 1; // Valid between 0 and 359
}
Aber das hängt davon ab, dass jemand anderes dies liest und Code schreibt. Wenn Sie es beispielsweise bearbeiten, wird die Einschränkung wie folgt:
message Foo
{
int32 bearing = 1; // Valid between -180 and +180
}
sie sind völlig abhängig von jedem Benutzer, der diese .proto-Software verwendet hat, um den Code zu aktualisieren. Das ist unzuverlässig und teuer.
Zumindest bei der Boost-Serialisierung verteilen Sie eine einzelne C++ - Klasse, und das kann die Gültigkeitsprüfung von Daten direkt beinhalten. Wenn sich diese Einschränkungen ändern, muss niemand sonst etwas tun, außer sicherzustellen, dass er dieselbe Version des Quellcodes verwendet wie Sie.
Alternative
Es gibt eine Alternative: ASN.1. Dies ist uralt, hat aber einige wirklich sehr nützliche Dinge:
Foo ::= SEQUENCE
{
bearing INTEGER (0..359)
}
Beachten Sie die Einschränkung. Wenn also jemand diese .asn-Datei verwendet, um Code zu generieren, erhält er Code, der automatisch überprüft, ob bearing
zwischen 0 und 359 liegt. Wenn Sie die .asn-Datei aktualisieren,
Foo ::= SEQUENCE
{
bearing INTEGER (-180..180)
}
sie müssen nur neu kompilieren. Es sind keine weiteren Codeänderungen erforderlich.
Sie können auch tun:
bearingMin INTEGER ::= 0
bearingMax INTEGER ::= 360
Foo ::= SEQUENCE
{
bearing INTEGER (bearingMin..<bearingMax)
}
Beachten Sie den <
. In den meisten Werkzeugen können auch LagerMin und LagerMax als Konstanten im generierten Code erscheinen. Das ist äußerst nützlich.
Einschränkungen können sehr aufwendig sein:
Garr ::= INTEGER (0..10 | 25..32)
Schauen Sie sich Kapitel 13 in diesem PDF an; Es ist erstaunlich, was du tun kannst.
Arrays können auch eingeschränkt werden:
Bar ::= SEQUENCE (SIZE(1..5)) OF Foo
Sna ::= SEQUENCE (SIZE(5)) OF Foo
Fee ::= SEQUENCE
{
boo SEQUENCE (SIZE(1..<6)) OF INTEGER (-180<..<180)
}
ASN.1 ist altmodisch, aber immer noch aktiv entwickelt, weit verbreitet (Ihr Mobiltelefon verwendet es häufig) und ist weitaus flexibler als die meisten anderen Serialisierungstechnologien. Der einzige Mangel, den ich sehen kann, ist, dass es keinen anständigen Code-Generator für Python gibt. Wenn Sie C/C++, C #, Java, ADA verwenden, sind Sie mit einer Mischung aus kostenlosen (C/C++, ADA) und kommerziellen Tools (C/C++, C #, Java) gut bedient.
Besonders gut gefällt mir die große Auswahl an binären und textbasierten Drahtformaten. Dies macht es in einigen Projekten äußerst praktisch. Die Liste der Drahtformate enthält derzeit:
0
und 15
eingeschränkt sind, beanspruchen nur 4 bits
auf der Leitung.) plus andere.
Beachten Sie die letzten beiden? Ja, Sie können Datenstrukturen in ASN.1 definieren, Code generieren und Meldungen in XML und JSON ausgeben/verbrauchen. Nicht schlecht für eine Technologie, die in den 80er Jahren begann.
Die Versionierung erfolgt anders als GPB. Sie können Erweiterungen berücksichtigen:
Foo ::= SEQUENCE
{
bearing INTEGER (-180..180),
...
}
Das bedeutet, dass ich zu einem späteren Zeitpunkt Foo
hinzufügen kann und ältere Systeme, auf denen diese Version installiert ist, noch funktionieren können (aber nur auf das Feld bearing
zugreifen können).
Ich schätze ASN.1 sehr hoch. Es kann schwierig sein, damit umzugehen (Werkzeuge könnten Geld kosten, der generierte Code ist nicht unbedingt schön usw.). Aber die Einschränkungen sind ein wirklich fantastisches Feature, das mir immer wieder jede Menge Herzschmerz erspart hat. Die Entwickler schreien viel, wenn die Encoder/Decoder melden, dass sie Duff-Daten generiert haben.
Andere Links:
Beobachtungen
Daten freigeben:
Um ehrlich zu sein, wenn GPB einen Zwangsmechanismus hinzufügt, wäre das der Gewinner. XSD ist nahe, aber die Werkzeuge sind fast überall Müll. Wenn es anständige Codegeneratoren für andere Sprachen gibt, wäre das JSON-Schema ziemlich gut.
Wenn GPB Einschränkungen hinzugefügt hätte (Hinweis: Dies würde keine der Drahtformate ändern), würde ich das für fast jeden Zweck jedem empfehlen. Obwohl ASN.1 uPER für Funkverbindungen sehr nützlich ist.
If GPB had constraints added (note: this would not change any of the wire formats), that'd be the one I'd recommend to everyone for almost every purpose. Though ASN.1's uPER is very useful for radio links.
Sie können die Boost-Serialisierung in enger Verbindung mit Ihren "echten" Domänenobjekten verwenden und die gesamte Objekthierarchie (Vererbung) serialisieren. Protobuf unterstützt keine Vererbung, daher müssen Sie die Aggregation verwenden. Die Leute argumentieren, dass Protobuf für DTOs (Datenübertragungsobjekte) und nicht für Kerndomänenobjekte selbst verwendet werden sollte. Ich habe sowohl boost :: serialization als auch protobuf verwendet. Die Leistung von boost :: serialization sollte berücksichtigt werden, cereal könnte eine Alternative sein.