Heim > Backend-Entwicklung > Python-Tutorial > Ursprüngliche Worte umgeschrieben: Eine unerwartete Entdeckung ist, dass das, was ursprünglich als Fehler angesehen wurde, tatsächlich ein Merkmal im Design von Protobuf ist

Ursprüngliche Worte umgeschrieben: Eine unerwartete Entdeckung ist, dass das, was ursprünglich als Fehler angesehen wurde, tatsächlich ein Merkmal im Design von Protobuf ist

PHPz
Freigeben: 2023-05-09 16:22:09
nach vorne
921 Leute haben es durchsucht

Hallo zusammen, ich bin großartig.

In unserem Projekt verwenden wir kürzlich das Protobuf-Format als Träger zum Speichern von Daten. Ich habe mir versehentlich ein großes Loch gegraben, aber es hat lange gedauert, bis ich es entdeckt habe.

protobuf Einführung

Protobufs vollständiger Name ist Protocol buffers und ist ein sprach- und plattformübergreifendes, erweiterbares Protokoll Mechanismus zur Serialisierung von Daten. Ähnlich wie XML, aber kleiner, schneller und einfacher. Sie müssen nur einmal definieren, wie Ihre Daten strukturiert sein sollen, und können dann die Generierungstools verwenden, um Quellcode zu generieren, der einige Serialisierungs- und Deserialisierungsvorgänge enthält. Strukturierte Daten können problemlos aus einer Vielzahl von Datenströmen und mit einer Vielzahl von Programmiersprachen geschrieben und gelesen werden.

Die Proto2-Version unterstützt die Codegenerierung in Java, Python, Objective-C und C++. Mit der neuen Proto3-Sprachversion können Sie auch Kotlin, Dart, Go, Ruby, PHP und C# sowie viele weitere Sprachen verwenden.

Wie hast du es gefunden?

In unserem neuen Projekt speichern wir die Daten des Projektlaufs im Protobuf-Format. Auf diese Weise können wir während des Debugging-Prozesses ein lokales Debugging basierend auf den vor Ort aufgezeichneten Daten durchführen.

message ImageData {
// ms
int64 timestamp = 1;
int32 id = 2;
Data mat = 3;
}

message PointCloud {
// ms
int64 timestamp = 1;
int32 id = 2;
PointData pointcloud = 3;
}

message State {
// ms
int64 timestamp = 1;
string direction = 2;
}

message Sensor {
repeated PointCloud point_data = 1;
repeated ImageData image_data = 2;
repeated State vehicle_data = 3;
}
Nach dem Login kopieren

Wir definieren einen solchen Datensatz und speichern dann, da die Bildraten der drei Datenquellen des Sensors unterschiedlich sind. Beim Speichern enthält ein einzelner Sensor tatsächlich nur einen Datensatz. , die beiden anderen Datenarten sind nicht enthalten.

Wir hatten kein Problem, als wir nur eine einzige Packung aufgenommen haben. Bis wir das Gefühl haben, dass ein einzelnes Paket längere Zeit nicht aufgezeichnet werden kann, müssen wir eine Lösung finden, um das Paket aufzuteilen.

Damals dachte ich, dass das sehr einfach sein muss. Wir richten ein Paket ein, um die nachfolgenden Daten in einem neuen Paket zu speichern, wenn es 500 Millionen erreicht. Ich habe es sehr reibungslos fertig geschrieben und es dann zur Datenaufzeichnung vor Ort abgelegt. Nachdem wir eine Weile aufgenommen hatten, nahmen wir das Paket zurück und simulierten das Testen unseres neuen Programms. Es wurde festgestellt, dass beim Parsen der Daten einiger Pakete ein Problem aufgetreten ist. Das Programm bleibt während der Ausführung hängen. Nach vielen Tests wurde festgestellt, dass dieses Problem bei einigen Paketen auftritt.

Was wir zunächst vermuteten, war, dass die Methode zur Beurteilung der Dateigröße falsch war, was sich auf die Vergabe von Unteraufträgen auswirkte. Denn bei der Beurteilung der Dateigröße wird die Datei geöffnet. Nachdem jedoch mehrere andere Möglichkeiten beurteilt worden waren, die Datei nicht zu öffnen, wurde die Aufteilung durchgeführt. Bei einigen der aufgezeichneten Pakete traten immer noch Probleme auf.

Erst dann kam mir der Verdacht, dass Protobuf einige besondere Anforderungen an die Datenspeicherung stellt. Später las ich einige Artikel und erfuhr, dass Protobuf Bezeichner benötigt, um mehrere Datensätze in einer Datei zu speichern. Andernfalls weiß protobuf beim Zurückparsen aus der Datei nicht, wo sich das Stoppzeichen einzelner Daten befindet, was zu Fehlern beim Parsen der Daten führt.

Hier erscheint diese Grube. Wir speichern eine Reihe von Daten in einem einzigen Paket ohne Trennoperationen. Beim Parsen von Protobuf werden alle Inhalte in der Datei in einem einzigen Sensor analysiert. Der Sensor enthält alle Daten und Protobuf führt alle gespeicherten Daten aktiv zusammen.

In diesem Moment stellte ich fest, dass bei der Aufzeichnung einzelner Pakete alle Daten korrekt waren. Das war wirklich mein Glück. protobuf wurde zufällig erfolgreich analysiert.

Wie kann man es lösen?

Da wir nun wissen, dass Protobuf auf diese Weise funktioniert, müssen wir nur noch wissen, wie man Protobuf teilt. Diese Methode ist wirklich schwer zu finden, weil es zu wenige Leute wie uns gibt, die sie anwenden. Die chinesische Suche kann diesen Inhalt überhaupt nicht finden. Möglicherweise verwendet nicht jeder Protobuf zum Speichern von Daten. Die Methode, die jeder verwendet, sollte das Szenario der Interaktion zwischen mehreren Diensten sein.

Endlich habe ich die Antwort durch einige Antworten zum Stackoverflow gefunden. Aus den Antworten habe ich erfahren, dass diese Lösung erst offiziell in Protobuf 3.3 integriert wurde. Es scheint, dass diese Funktion wirklich selten verwendet wird.

bool SerializeDelimitedToOstream(const MessageLite& message,
 std::ostream* output);
bool ParseDelimitedFromZeroCopyStream(
MessageLite* message, io::ZeroCopyInputStream* input, bool* clean_eof);
Nach dem Login kopieren

Durch dieses Methodenpaar können Dateien entsprechend dem Datenfluss einzeln gespeichert und gelesen werden. Machen Sie sich keine Sorgen mehr darüber, dass Daten zusammengeführt und gelesen werden.

Natürlich können die auf diese Weise gespeicherten Daten nicht mit der ursprünglichen Analysemethode analysiert werden, und das Speicherformat hat sich vollständig geändert. Diese Methode speichert zuerst die Größe der Binärdaten und dann die Binärdaten.

Fazit

Nach langem Hin und Her bin ich endlich durch diese Segmentierungsgrube gekommen. Das Nutzungsszenario kann relativ nischenorientiert sein, was dazu führt, dass viele Informationen überhaupt nicht gefunden werden können. Ich habe diese Probleme entdeckt, indem ich mir den Quellcode selbst angesehen habe. Der Quellcode von C++ ist wirklich schwer zu lesen. Es gibt viele Vorlagenmethoden und Vorlagenklassen, und es ist leicht, einige Details zu übersehen. Schließlich habe ich mir den C#-Code angesehen und ihn schließlich bestätigt.

Das obige ist der detaillierte Inhalt vonUrsprüngliche Worte umgeschrieben: Eine unerwartete Entdeckung ist, dass das, was ursprünglich als Fehler angesehen wurde, tatsächlich ein Merkmal im Design von Protobuf ist. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:51cto.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage