C'è sempre un buon momento per utilizzare Int32, invece di sint32 in Google buffer protocollo?

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

  •  12-09-2019
  •  | 
  •  

Domanda

Ho letto su Google buffer protocollo di recente, che permette una varietà dei tipi di valore scalare per essere utilizzato nei messaggi.

loro documentazione , ci sono tre tipi di variabili primitivi interi -Lunghezza - int32, uint32 e sint32. Nella loro documentazione, si nota che int32 è "inefficiente per la codifica di numeri negativi - se il campo può avere valori negativi, utilizzare sint32 invece." Ma se si dispone di un campo che non ha i numeri negativi, suppongo che Uint32 sarebbe un tipo di meglio da usare rispetto int32 comunque (a causa della qualcosa in più ed è diminuito il costo della CPU del trattamento numeri negativi).

Così, quando sarebbe int32 essere un buon scalare da usare? È la documentazione che implica che è più efficiente solo quando raramente si ottiene numeri negativi? O è sempre preferibile utilizzare sint32 e uint32, a seconda del contenuto del campo?

(Le stesse domande si applicano alle versioni a 64 bit di questi scalari così:. int64, uint64 e sint64, ma li ho lasciati fuori la descrizione del problema per l'amor di leggibilità)

È stato utile?

Soluzione

Non ho dimestichezza con Google Protocol Buffer, ma la mia interpretazione della documentazione è:

  • uso uint32 se il valore non può essere negativo
  • uso sint32 se il valore è più o meno la stessa probabilità di essere negativo come non (per qualche definizione sfocata di "la stessa probabilità di essere")
  • uso int32 se il valore potrebbe essere negativo, ma questo è molto meno probabile rispetto al valore di essere positivo (ad esempio, se l'applicazione utilizza talvolta -1 per indicare un errore o un valore 'sconosciuto' e questa è una situazione relativamente raro)

Ecco quello che i documenti hanno da dire sulle codifiche ( http: / /code.google.com/apis/protocolbuffers/docs/encoding.html#types ):

  

v'è una differenza importante tra i tipi Acceso int (sint32 e sint64) ei tipi int "standard" (int32 e int64) quando si tratta di codifica numeri negativi. Se si utilizza int32 o int64 come il tipo per un numero negativo, il varint risultante è sempre dieci byte lunghi - è, in modo efficace, trattato come un grande numero intero senza segno. Se si utilizza uno dei tipi firmati, il varint risultante utilizza la codifica ZigZag, che è molto più efficiente.

     

codifica zigzag mappe interi firmato interi senza segno in modo che i numeri con un piccolo valore assoluto (ad esempio, -1) hanno un piccolo varint codificato valore troppo. Si fa in modo che "zig-zag" avanti e indietro attraverso i numeri interi positivi e negativi, cosicché -1 è codificato come 1, 1 è codificato come 2, -2 viene codificato come 3, e così via ...

Quindi sembra che anche se l'utilizzo dei numeri negativi è raro, a patto che la grandezza dei numeri (compresi i numeri non negativi) si sta passando nel protocollo si trova sul lato più piccola, si potrebbe essere meglio utilizzando sint32. Se non siete sicuri, profilazione sarebbe in ordine.

Altri suggerimenti

C'è molto poco buona ragione per usare mai int * piuttosto che sint *. L'esistenza di questi tipi di più è più probabile per storico, a ritroso motivi di compatibilità, che buffer protocollo cerca di mantenere, anche attraverso le proprie versioni del protocollo.

La mia ipotesi migliore è che nella prima versione che stupidamente codificati interi negativi nella rappresentazione complemento a 2, che richiede la codifica varint massimo dimensioni di 9 byte (senza contare il tipo di byte in più). Poi sono stati bloccati con che codifica in modo da non rompere il vecchio codice e serializzazioni che già usato. Così, avevano bisogno di aggiungere un nuovo tipo di codifica, sint *, per ottenere una codifica più dimensionata in modo variabile per i numeri negativi, mentre non rompere il codice esistente. Come i progettisti non si sono resi conto questo problema dal get-go è completamente al di là di me.

La codifica varint (senza specificazione tipo, che richiede più 1 byte) può codificare un valore intero nel seguente numero di byte:

[0, 2 ^ 7): un byte

[2 ^ 7, 2 ^ 14): due byte

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

[2 ^ 21, 2 ^ 28): quattro byte

[2 ^ 28, 2 ^ 35): cinque byte

[2 ^ 35, 2 ^ 42): sei byte

[2 ^ 42, 2 ^ 49): sette byte

[2 ^ 49, 2 ^ 56): otto byte

[2 ^ 56, 2 ^ 64): nove byte

Se si vuole codificare simile piccola magnitudo interi negativi compatto allora si avrà bisogno di "consumare" un bit per indicare il segno. È possibile farlo attraverso un bit esplicito segno (ad un certo posizione riservata) e rappresentazione in modulo. In alternativa, si può fare la codifica a zig zag, che fa effettivamente la stessa cosa dalla sinistra spostando la grandezza di 1 bit e sottraendo 1 per i numeri negativi (in modo che il bit meno significativo indica il segno: Evens sono non negativo, le probabilità sono negativi).

In entrambi i casi, il taglio su punti in cui positivo interi richiedono più spazio ora arriva un fattore di 2 in precedenza:

[0, 2 ^ 6): un byte

[2 ^ 6, 2 ^ 13): due byte

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

[2 ^ 20, 2 ^ 27): quattro byte

[2 ^ 27, 2 ^ 34): cinque byte

[2 ^ 34, 2 ^ 41): sei byte

[2 ^ 41, 2 ^ 48): sette byte

[2 ^ 48, 2 ^ 55): otto byte

[2 ^ 55, 2 ^ 63): nove byte

Per fare il caso di usare int * sopra sint *, numeri negativi dovrebbero essere estremamente raro, ma possibile, e / o i valori positivi più comuni che ci si aspetta per codificare avrebbero dovuto cadere proprio dietro uno dei cut over punti che conduce ad una codifica più grande in sint * rispetto a int * (es - 2 ^ 6 contro 2 ^ 7 che porta a 2x dimensioni codificante)

.

In sostanza, se avete intenzione di avere i numeri in cui alcuni possono essere negativi, poi con l'uso sint impostazione predefinita * piuttosto che int *. int * sarà molto raramente essere superiore e di solito non sarà nemmeno la pena extra pensiero che avete da dedicare verso giudicare se vale la pena o no IMHO.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top