2015-11-26 131 views
6

ZigZag需要大量的開銷來編寫/讀取數字。事實上,我驚呆了,看到它不僅僅寫出int/long值,而且還有很多額外的加擾。甚至有一個循環涉及: https://github.com/mardambey/mypipe/blob/master/avro/lang/java/avro/src/main/java/org/apache/avro/io/DirectBinaryEncoder.java#L90Protocol Buffers和Avro中ZigZag編碼背後的原因是什麼?

我似乎無法在協議緩衝區文檔或Avro文檔中找到,或自我推理,這樣的數字的優勢是什麼?爲什麼在編碼後交替使用正數和負數會更好?

爲什麼他們不只是寫在小端,大端,網絡秩序,只需要將它們讀入內存,並可能反轉位的字節順序?我們用性能購買什麼?

+2

如果您對protobuf-like的東西感興趣,那麼它不會執行昂貴的varint編碼,請參閱https://capnproto.org。它速度更快,但它確實需要更多空間。 (披露:我是Cap'n Proto的作者,也是Google的大部分開源Protobuf代碼的作者。) –

+0

@KentonVarda感謝您的信息,我不知道Cap'n'proto。添加到我的協議工具欄。 – Endrju

+0

協議緩衝區至少從版本2開始,讓我們使用固定大小的編碼整數(例如 - fixed32,sfixed64等),如果這對您的應用程序更有意義。例如,如果您的值將在可能的值範圍內均勻分佈,那麼您希望使用固定格式而不是變量格式。這就是說,在這種簡單的可變長度編碼可以節省大量空間的情況下,通常使用的數值更接近於零。 – jschultz410

回答

8

它是一個可變長度的7位編碼。編碼值的第一個字節將其高位設置爲0,後續字節將其設置爲1.解碼器可以告訴用戶使用了多少字節來對該值進行編碼。無論機器架構如何,字節順序總是小端的。

這是一種編碼技巧,允許根據需要寫入儘可能少的字節來對值進行編碼。因此,一個8字節的長的的值在-64和63之間只需要一個字節。這是常見的,提供的範圍在實踐中很少使用。

沒有gzip式壓縮方法的開銷,將數據緊緊包裝起來是設計目標。也用於.NET Framework。編譯/解碼該值所需的處理器開銷是無關緊要的。已經遠遠低於壓縮方案,這只是I/O成本的一小部分。

+1

非常感謝。我非常感謝你的幫助。現在它非常有意義。我迷路了,因爲我已經開始考慮在某些地方[不必要地混淆]的Java源代碼(https://github.com/mardambey/mypipe/blob/master/avro/lang/java/avro/src /main/java/org/apache/avro/io/BinaryDecoder.java#L195)。天哪,Java真的需要手工製作的循環展開代碼才能快速工作? – Endrju

+0

@Endrju:低級庫協議的性能要求非常高,因爲這樣的庫的用戶差異很大。庫代碼擁有非常多樣化的客戶端,其中一些客戶端有嚴格的性能要求。此外,庫代碼有成爲瓶頸的趨勢,所以優化庫通常是至關重要的。性能通常是選擇庫時的首要考慮因素。 – Brian

+0

@Brian我知道我知道,但...循環展開?在所有這些年份和版本之後,Java JITter能不能同樣好或更好?...... – Endrju

相關問題