Gibt es überhaupt eine gute Zeit int32 statt sint32 in Google Protocol Buffers zu benutzen?

StackOverflow https://stackoverflow.com/questions/765916

  •  12-09-2019
  •  | 
  •  
War es hilfreich?

Lösung

Ich bin nicht vertraut mit Google Protocol Buffers, aber meine Interpretation der Dokumentation ist:

  • Verwendung uint32, wenn der Wert kann nicht negativ sein
  • Verwendung sint32, wenn der Wert ziemlich genau so wahrscheinlich ist wie nicht negativ zu sein (für einige unscharfe Definition des Begriffs „als wahrscheinlich zu sein“)
  • Verwendung int32 wenn der Wert negativ sein könnte, aber das ist viel weniger wahrscheinlich als der Wert positiv ist (zum Beispiel, wenn die Anwendung verwendet manchmal -1 einen Fehler anzuzeigen oder ‚unbekannt‘ Wert und dies ist eine relativ seltene Situation)

Hier ist, was die Dokumentation über die Kodierungen zu sagen haben ( http: / /code.google.com/apis/protocolbuffers/docs/encoding.html#types ):

  

es ein wichtiger Unterschied zwischen den signed int-Typen (sint32 und sint64) und den „Standard“ int-Typen (int32 und int64), wenn es negative Zahlen codieren, kommt. Wenn Sie int32 oder int64 als Typ für eine negative Zahl zu verwenden, ist die resultierende varint immer zehn Bytes lang - es ist effektiv, wie eine sehr große ganze Zahl ohne Vorzeichen behandelt. Wenn Sie eine der signierten Typen verwenden, verwendet die resultierende varint ZigZag-Codierung, die viel effizienter ist.

     

ZigZag Codierung Karten ganze Zahlen ganze Zahlen ohne Vorzeichen unterzeichnet, so dass die Zahlen mit einem kleinen absoluten Wert (zB -1) ein kleine varint Wert zu codiert haben. Es tut dies in einer Weise, dass „Zick-Zack“ hin und her durch die positive und negative ganze Zahlen sind, so daß -1 codiert ist als 1, 1, wie 2 codiert wird, als -2 3 codiert ist, und so weiter ...

So wie es aussieht, auch wenn Ihre Verwendung von negativen Zahlen ist selten, solange die Größe der Zahlen (einschließlich nicht-negative Zahlen) Sie im Protokoll vorbei auf der kleineren Seite ist, dass Sie vielleicht besser dran mit sint32. Wenn Sie nicht sicher sind, dann wäre Profilierung um.

Andere Tipps

Es gibt sehr wenig Grund zu je int verwenden * statt sint *. Die Existenz dieser zusätzlichen Typen ist höchstwahrscheinlich für historische, Rückwärtskompatibilität Gründe, die Protocol Buffers auch über seine eigenen Protokollversionen zu halten versucht.

Meine beste Vermutung ist, dass in der frühesten Version sie negative ganze Zahlen dumbly codiert in 2-Darstellung, die die maximal Größe VarInt Codierung von 9 Bytes benötigt (nicht die zusätzliche Typenbyte mitgezählt). Dann wurden sie mit dieser Codierung fest, um nicht alten Code und Serialisierung zu brechen, die bereits daran gewöhnt. Also, sie brauchte einen neuen Codierungstyp, sint *, hinzufügen, um eine bessere variabel bemessen Codierung für negative Zahlen zu bekommen, während nicht vorhandenen Code zu brechen. Wie die Designer nicht erkennen, dieses Problem aus dem get-go ist ganz über mich.

Die VarInt Codierung (ohne Typangabe, die 1 Byte erfordert mehr) kann einen unsignierten Ganzzahl-Wert in der folgenden Anzahl von Bytes kodieren:

[0, 2 ^ 7): ein Byte

[2 ^ 7, 2 ^ 14): zwei Bytes

[2 ^ 14 2 ^ 21): drei Bytes

[2 ^ 21, 2 ^ 28): vier Bytes

[2 ^ 28, 2 ^ 35): fünf Bytes

[2 ^ 35, 2 ^ 42): sechs Bytes

[2 ^ 42, 2 ^ 49): sieben Bytes

[2 ^ 49, 2 ^ 56): acht Bytes

[2 ^ 56, 2 ^ 64): neun Bytes

Wenn Sie möchten, um in ähnlicher Weise kompakt kleine Größe negative ganze Zahlen kodieren, dann werden Sie brauchen, um ein Bit zu „verbrauchen“, um die Zeichen anzuzeigen. Sie können dies durch eine explizite Vorzeichenbit tun (bei einigen reservierten Position) und Größendarstellung. Oder Sie können Zick-Zack-Codierung tun, die effektiv das gleiche tut, indem links die Größe von 1-Bit-Verschiebung und Subtrahieren von 1 für negative Zahlen (so das am wenigsten signifikante Bit gibt das Vorzeichen: Evens sind nicht-negativ, stehen die Chancen negativ).

So oder so, der Schnitt über Punkte, an denen positive ganze Zahlen erfordern mehr Platz kommt nun einen Faktor 2 früher:

[0, 2 ^ 6): ein Byte

[2 ^ 6, 2 ^ 13): zwei Bytes

[2 ^ 13, 2 ^ 20): drei Bytes

[2 ^ 20, 2 ^ 27): vier Bytes

[2 ^ 27, 2 ^ 34): fünf Bytes

[2 ^ 34, 2 ^ 41): sechs Bytes

[2 ^ 41, 2 ^ 48): sieben Bytes

[2 ^ 48 2 ^ 55): acht Bytes

[2 ^ 55, 2 ^ 63): neun Bytes

Um den Fall zu machen, um int * über sint * zu verwenden, negative Zahlen würden extrem selten sein müssen, aber möglich, und / oder die häufigsten positiven Werte, die Sie erwarten würden zu kodieren fallen müssen gleich um einen des Schnittes vorbei Punkte, die auf eine größere Codierung in sint führt * wie in int * entgegengesetzt (zB - 2 ^ 6 vs. 2 ^ 7 führenden kodierend Größe zu 2x)

.

Grundsätzlich, wenn Sie vorhaben, Zahlen haben, wo einige negativ sein kann, dann durch die Verwendung sint Standard * statt int *. int * wird sehr selten überlegen und in der Regel wird die zusätzliche nicht einmal wert, haben Sie zu urteilen widmen, ob es sich lohnt oder nicht IMHO.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top