2015-11-26 10 views
6

ZigZag richiede un sacco di spese generali per scrivere/leggere i numeri. In realtà sono rimasto sbalordito nel constatare che non solo scrive valori int/long così come sono, ma fa un sacco di ulteriori rimescolamenti. C'è anche un ciclo coinvolti: https://github.com/mardambey/mypipe/blob/master/avro/lang/java/avro/src/main/java/org/apache/avro/io/DirectBinaryEncoder.java#L90Qual è il motivo della codifica ZigZag in Protocol Buffers e Avro?

Non mi sembra di essere in grado di trovare in buffer protocollo documenti o in documenti Avro, o ragionare me stesso, qual è il vantaggio di scrambling numeri del genere? Perché è meglio avere numeri positivi e negativi alternati dopo la codifica?

Perché non sono solo scritti in little-endian, big-endian, ordine di rete che richiederebbe solo di leggerli in memoria e possibilmente invertire bit-endianness? Cosa acquistiamo pagando con le prestazioni?

+2

Se sei interessato a qualcosa di protobuf che non fa costose codifiche varint, vedi https://capnproto.org. È più veloce ma richiede più spazio sul cavo. (Divulgazione: Sono l'autore di Cap'n Proto e anche l'autore della maggior parte del codice Protobuf open source di Google.) –

+0

@KentonVarda Grazie per le informazioni, non ero a conoscenza di Cap'n'proto. Aggiunto al mio protocollo Toolbelt. – Endrju

+0

I buffer di protocollo, almeno a partire dalla versione 2, consentono di utilizzare numeri interi codificati a dimensione fissa (ad es. - fixed32, sfixed64, ecc.) Se questo ha più senso per l'applicazione. Ad esempio, se i tuoi valori saranno distribuiti uniformemente attraverso il possibile intervallo di valori, allora vuoi usare la forma fissa piuttosto che la forma variabile. Detto questo, è molto comune per valori comunemente usati raggruppare vicino a zero dove questo tipo di codifica a lunghezza variabile può risparmiare molto spazio. – jschultz410

risposta

8

È una codifica a 7 bit di lunghezza variabile. Il primo byte del valore codificato ha bit alto impostato a 0, i byte successivi lo hanno a 1. Quale è il modo in cui il decodificatore può indicare quanti byte sono stati usati per codificare il valore. L'ordine dei byte è sempre little-endian, indipendentemente dall'architettura della macchina.

È un trucco di codifica che consente di scrivere pochi byte necessari per codificare il valore. Quindi un 82 byte lungo con un valore compreso tra -64 e 63 richiede solo un byte. Che è comune, l'intervallo fornito da lungo è utilizzato molto raramente nella pratica.

L'obiettivo di progettazione è stato quello di impacchettare i dati senza l'overhead di un metodo di compressione in stile gzip. Utilizzato anche nello .NET Framework. Il sovraccarico del processore necessario per en/decodificare il valore è irrilevante. Già molto più basso di uno schema di compressione, è una frazione molto piccola del costo I/O.

+1

Grazie mille. Apprezzo molto il vostro aiuto. Ora ha perfettamente senso. Mi sono perso perché ho iniziato a cercare fonti Java che sono [inutilmente confuse in alcuni punti] (https://github.com/mardambey/mypipe/blob/master/avro/lang/java/avro/src /main/java/org/apache/avro/io/BinaryDecoder.java#L195). Caspita, Java ha davvero bisogno del codice di srotolamento del ciclo artigianale per funzionare velocemente? – Endrju

+0

@Endrju: I requisiti di prestazioni per i protocolli di libreria di basso livello sono incredibilmente elevati, poiché gli utenti di tali librerie variano molto. il codice della libreria ha una collezione molto diversificata di client, alcuni dei quali hanno requisiti di prestazioni elevati. Inoltre, il codice della libreria tende a diventare un collo di bottiglia, quindi l'ottimizzazione delle librerie è spesso di vitale importanza. Le prestazioni sono spesso di primaria importanza quando si selezionano le librerie. – Brian

+0

@ Brian so che lo so ma ... lo srotolamento del circuito? JITter non può Java dopo tutti quegli anni e versioni che lo fanno altrettanto bene - o meglio? ... – Endrju

Problemi correlati