¿Hay siempre un buen momento para utilizar int32 en lugar de Sint32 en Google Protocol Buffers?

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

  •  12-09-2019
  •  | 
  •  

Pregunta

He estado leyendo sobre Google Protocol Buffers recientemente, lo que permite una variedad de los tipos de valor escalares para ser utilizado en los mensajes.

De acuerdo con su documentación , hay tres tipos de variables primitivas enteros -Longitud - int32, uint32, y sint32. En su documentación, señalan que int32 es "ineficiente para codificar los números negativos - si el campo es probable que tenga valores negativos, usar sint32 en su lugar." Pero si usted tiene un campo que no tiene números negativos, supongo que uint32 habría un mejor tipo de uso que de todos modos int32 (debido al poco más y reducido el coste de CPU de procesamiento de números negativos).

Así que cuando se int32 ser un buen escalar a utilizar? Es la documentación dando a entender que es más eficiente sólo cuando rara vez tienen números negativos? O es siempre preferible utilizar sint32 y uint32, en función de los contenidos del campo?

(Las mismas preguntas se aplican a las versiones de 64 bits de estos escalares, así:. int64, uint64 y sint64; pero los dejaron fuera de la descripción del problema por el bien de facilitar la lectura)

¿Fue útil?

Solución

No estoy familiarizado con Google Protocol Buffers, pero mi interpretación de la documentación es:

  • Uso uint32 si el valor no puede ser negativa
  • Uso sint32 si el valor es más o menos las mismas probabilidades de ser negativo como no (por alguna difusa definición de "probabilidad de ser")
  • uso int32 si el valor podría ser negativa, pero que es mucho menos probable que el valor de ser positivo (por ejemplo, si la aplicación utiliza a veces -1 para indicar un error o valor 'desconocido' y esta es una situación relativamente poco frecuente)

Esto es lo que los doctores tienen que decir acerca de las codificaciones ( http: / /code.google.com/apis/protocolbuffers/docs/encoding.html#types ):

  

existe una diferencia importante entre los tipos firmados int (sint32 y sint64) y los tipos int "estándar" (int32 y int64) cuando se trata de codificar los números negativos. Si utiliza int32 o int64 como el tipo para un número negativo, el varint resultante es siempre diez bytes de longitud - que es, efectivamente, tratado como un entero sin signo muy grande. Si utiliza uno de los tipos firmados, el varint resultante utiliza la codificación zigzag, que es mucho más eficiente.

     

ZigZag codificación mapas de enteros con signo de enteros sin signo de modo que los números con un pequeño valor absoluto (por ejemplo, -1) tienen una pequeña varint valor codificado también. Esto se hace de una manera que "zig-zags" de ida y vuelta a través de los números enteros positivos y negativos, de modo que -1 se codifica como 1, 1 se codifica como 2, -2 se encuentra codificado como 3, y así sucesivamente ...

Así que parece que incluso si su uso de números negativos es raro, siempre y cuando la magnitud de los números (incluidos los números no negativos) que está pasando en el protocolo está en el lado más pequeño, es posible que sea mejor utilizando sint32. Si no está seguro, perfiles estaría en orden.

Otros consejos

Hay muy poca buena razón para usar siempre int * * en lugar de sint. La existencia de estos tipos adicionales es más probable por razones históricas, hacia atrás razones de compatibilidad, que Protocol Buffers trata de mantener incluso a través de sus propias versiones de protocolo.

Mi mejor conjetura es que en la versión más antigua que sin decir nada codificados enteros negativos en representación de complemento a 2, lo que requiere la codificación varint tamaño máximo de 9 bytes (sin contar el tipo byte adicional). Luego fueron atrapados con la que codifica el fin de no romper el código antiguo y serializaciones que ya se utilizaron. Por lo tanto, tenían que añadir un nuevo tipo de codificación, sint *, para obtener una mejor codificación de tamaño variable para los números negativos sin romper el código existente. ¿Cómo los diseñadores no se dan cuenta de este problema desde el primer momento es totalmente más allá de mí.

La codificación varint (sin especificación de tipo, que requiere 1 más byte) puede codificar un valor entero sin signo en el siguiente número de bytes:

[0, 2 ^ 7): un byte

[2 ^ 7, 2 ^ 14): dos bytes

[2 ^ 14, 2 ^ 21): tres bytes

[2 ^ 21, 2 ^ 28): cuatro bytes

[2 ^ 28, 2 ^ 35): cinco bytes

[2 ^ 35, 2 ^ 42): seis bytes

[2 ^ 42, 2 ^ 49): siete bytes

[2 ^ 49, 2 ^ 56): ocho bytes

[2 ^ 56, 2 ^ 64): nueve bytes

Si desea codificar de manera similar enteros negativos de magnitud pequeña compacta, entonces necesitará a "agotar" un bit para indicar el signo. Usted puede hacer esto a través de un bit de signo explícito (en alguna posición reservada) y la representación de magnitud. O bien, puede hacer zig codificación zag, lo que efectivamente hace lo mismo al cambiar izquierda de la magnitud de 1 bit y restando 1 para los números negativos (por lo que el bit menos significativo indica el signo: iguala no son negativos, las probabilidades son negativos).

De cualquier manera, el corte sobre puntos en los que positivo enteros requieren más espacio ahora viene un factor de 2 anterior:

[0, 2 ^ 6): un byte

[2 ^ 6, 2 ^ 13): dos bytes

[2 ^ 13, 2 ^ 20): tres bytes

[2 ^ 20, 2 ^ 27): cuatro bytes

[2 ^ 27, 2 ^ 34): cinco bytes

[2 ^ 34, 2 ^ 41): seis bytes

[2 ^ 41, 2 ^ 48): siete bytes

[2 ^ 48, 2 ^ 55): ocho bytes

[2 ^ 55, 2 ^ 63): nueve bytes

Para hacer el caso de utilizar int * sobre sint *, los números negativos tendrían que ser extremadamente rara, pero posible, y / o los valores positivos más comunes que se pueden esperar para codificar tendrían que caer a la vuelta de uno de los cortar durante puntos que conduce a una codificación más grande en sint * en contraposición a int * (por ejemplo, - 2 ^ 6 vs. 2 ^ 7 que conduce a 2x que codifica tamaño)

.

Básicamente, si usted va a tener números donde algunos pueden ser negativos, entonces por defecto el uso sint * en vez de int *. int * será muy raramente es superior y por lo general ni siquiera vale la pena el extra pensado que se debe dedicar a juzgar si vale la pena o no en mi humilde opinión.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top