Protoc Buffer 優化傳輸大小的乙個細節

2021-09-24 22:41:37 字數 1796 閱讀 2673

protoc buffer 是我們比較常用的序列化框架,protocol buffer 序列化後的佔空間小,傳輸高效,可以在不同程式語言以及平台之間傳輸。今天這篇文章主要介紹 protocol buffer 使用 varint32 減少序列化後的資料大小。

varint32 編碼

varint32 (vary int 32),即:長度可變的 32 為整型型別。一般來說,int 型別的長度固定為 32 位元組。但 varint32 型別的資料長度是不固定的,varint32 中每個位元組的最高位有特殊的含義。如果最高位為 1 代表下乙個位元組也是該數字的一部分。因此,表示乙個整型數字最少用 1 個位元組,最多用 5 個位元組表示。如果某個系統中大部分數字需要 = 4 位元組才能表示,那其實並不適合用 varint32 來編碼。下面以乙個例子解釋 varint32 的編碼方式:

以129為例,它的二進位制為10000001。由於每個位元組最高位用於特殊標記,因此只能有7位儲存資料。第乙個位元組儲存最後7位(0000001),但並沒有存下所有的位元,因此最高位置位1,剩下的部分用後續位元組表示。所以,第乙個位元組為:10000001第二個位元組只儲存乙個位元位即可,因此最高位為0,所以,第二個位元組為:00000001這樣,我們就不必用4位元組的整型儲存129,可以節省儲存空間

在 protoc buffer 中,每乙個 protobuf 物件都有乙個方法public void writedelimitedto(final outputstream output),該方法將 protobuf 物件序列化後的長度以及序列化資料本身寫入到輸出流 output 中。多個物件呼叫該方法可以將序列化後的資料寫入到同乙個輸出流。由於每次寫入都有長度,所以反序列化時先解析長度,在讀取對應長度的位元組資料,即可解析出每個物件。該方法中對序列化後長度的編碼便使用 varint32,因為乙個 protobuf 物件序列化後的長度不會太大,因此使用 varint32 編碼能夠有效的節省儲存空間。接下來我們看下 protoc buffer 中如何實現 varint32 編碼,跟進 writedelimitedto 方法,可以看到 varint32 編碼的原始碼如下:

該方法對 int 型別的值進行 varint32 編碼,可以驗證最多 5 個位元組即可完成編碼。

varint32 解碼

理解了編碼後,解碼就沒什麼可說的了。就是從輸入位元組流中,讀取乙個位元組判斷最高位,將真實資料位拼接成最終的數字即可。hadoop rpc 中使用了 protoc buffer 作為資料序列化框架。其中,hadoop 針對 writedelimitedto 方法實現了對 varint32 的解碼。原始碼如下:

在 hadoop 原始碼中並沒有使用迴圈去解碼,而是使用多個 if 條件判斷,根據 tmp 的正負號來判斷最高位是否是 1。如果讀取的該數字用了 5 個位元組編碼,當讀到了第 5 個位元組,理論上 tmp 應該大於 0 。但是如果 tmp 小於 0 ,說明編碼格式有問題。在 hadoop 原始碼中程式會繼續往下讀,最多再向下讀 5 個位元組且丟掉最高位仍然 0 的位元組。如果在該過程某個位元組最高位為 0 ,便停止讀取直接返回。這個處理邏輯在其他框架原始碼中也有出現。

看完 hadoop 的原始碼,我們在看看 protoc buffer 自己提供的解析原始碼:

可以看到 protoc buffer 自己提供的解碼方式與 hadoop 是一樣的,包括遇到錯誤的編碼時候的異常處理方式也是一樣的。

小結本篇文章主要介紹了 varint32 編譯碼,varint32 表示乙個整型數字最少用 1 個位元組, 最多用 5 個位元組。所以在傳輸數字大部分都比較小的場景下適合使用。當然,我們也可以用 varint64 來表示長整型的數字。 在介紹 varint32 的同時我們也看到了 protobuf 和 hadoop 這樣的框架在傳輸資料的優化上不放過任何乙個細節,值得我們學習。

效能優化 Android群英傳

1 布局優化 1 避免overdraw 2 優化布局層級 降低view樹的高度。3 避免巢狀過多無用布局 4 使用標籤重用layout 5 使用實現view的延遲載入,是乙個輕量級的元件,不僅不可視,而且大小為0.需要的時候再顯示。兩種方式顯示這個view。mviewstub.setvisibili...

傳值 傳引用 傳指標

收藏 相關概念 c 三種傳遞引數方式 傳引數的值 稱值傳遞,簡稱傳值 傳引數的位址 稱位址傳遞,簡稱為傳址 和引用傳遞 稱為傳引用 相應的函式傳值呼叫,傳址呼叫和傳引用呼叫 形參 實參 函式定義時參數列中的引數稱為形式引數,簡稱形參 函式呼叫時參數列中的引數稱為實際引數,簡稱實參。實參和形參之間的資...

傳值 傳引用 傳指標

相關概念 c 三種傳遞引數方式 傳引數的值 稱值傳遞,簡稱傳值 傳引數的位址 稱位址傳遞,簡稱為傳址 和引用傳遞 稱為傳引用 相應的函式傳值呼叫,傳址呼叫和傳引用呼叫 形參 實參 函式定義時參數列中的引數稱為形式引數,簡稱形參 函式呼叫時參數列中的引數稱為實際引數,簡稱實參。實參和形參之間的資料傳遞...