Protocol Buffer Varint編碼簡介 與Lua 訪問PB int_64

1.Protocol Buffer編碼

什么是Protocol Buffer(下稱pb),這邊也就不介紹了阻星,通常要求不是特別嚴(yán)格的時候Json,甚至XML就能滿足要求妥箕。
如需了解這邊傳送門:

https://developers.google.com/protocol-buffers/

message Test1 { required int32 a = 1; }
pb以二進(jìn)制形式存儲更舞,以Base 128 Varints進(jìn)行編碼畦幢,Test1的存儲內(nèi)容僅為3個字節(jié):

08 96 01

這是什么意思呢缆蝉?

Varints are a method of serializing integers using one or more bytes. Smaller numbers take a smaller number of bytes.
Each byte in a varint, except the last byte, has the most significant bit (msb) set – this indicates that there are further bytes to come. The lower 7 bits of each byte are used to store the two's complement representation of the number in groups of 7 bits, least significant group first.

在Varints中,每個Byte的取低7位進(jìn)行存儲實際內(nèi)容刊头。最高位用1來表示most significant bit,既表示下一個Byte跟當(dāng)前Byte存儲的是同一個Varint印颤;用0來表示least significant bit看完這里年局,相信大家知道咸产,對于一個完全的int64,其實用varints真實物理存儲會超過64位矢否。

那么接下來解釋Test1的存儲脑溢,首先先一張表

Type Meaning Used For
0 Varint int32, int64, uint32, uint64, sint32, sint64, bool, enum
1 64-bit fixed64, sfixed64, double
2 Length-delimited string, bytes, embedded messages, packed repeated fields
3 Start group groups (deprecated)
4 End group groups (deprecated)
5 32-bit fixed32, sfixed32, float

當(dāng)一個Message被encode的時候,message的key其實只存了filed number以及一個wire type,filed number被你定義在.proto文件中屑彻,wire type即上面的表格中對應(yīng)的。
每一個varint key 為 field_number << 3 | wire_type壶谒,言下之意,一個varint key的某三位存的是wire type,后4位存的是filed number。
以Test1為例陨界,我們知道第一Byte通常就是varint key,Test1的內(nèi)容是 08菌瘪,也就是:
000 1000
于是我們有filed number = 0001,wire type = 0阱当。因此我們也得到了如下信息,在filed number = 1的地方 存儲著一個varint俏扩。
然后我們接下去讀
96 01 = 1001 00110 0000 0001
基于varint的存儲表示: 000 0001 001 00110 -> 10010110 = 150
所以我們知道存儲的值為150弊添。

2.Lua PB 與int_64

情景是這樣的,我們有一個server用的是openresty油坝,語言用的是lua,lua的解釋器是luajit澈圈。至于為什么是luajit,我就不展開了窍帝,我們直奔主題,luajit是不支持int_64盯桦。但是可以通過ffi,間接的操作int_64拥峦。
lua本身也沒有官方支持的pb解釋器卖子,我們用的是下面這個庫:

https://github.com/Neopallium/lua-pb
但是之前這個庫在pack int_64的時候有一個BUG(在我們同事提了issue后,剛剛上去看了一下已修復(fù),囧rz。羽利。这弧。)

但我還是把老代碼翻出來吧(要不然就寫不下去了- -皇帮,只能怪自己手慢属拾,再他沒更新的時候?qū)懢投嗪冒渐白。?/p>

Bug.jpeg

先稍微解釋一下這個方法,h存的是高32位虏劲,l則是低32位柒巫。
每次取7位堡掏,然后第八位補(bǔ)1,進(jìn)行一個遞歸(如有不懂見上部分)。
理想的是遞歸4次后扮休,再處理高位。但是有一個問題八堡,就是如果地位是一個比較小的值,于是就可以遞歸1-3三次后就開始處理高位了,于是就值就出錯了叔壤。
我們最終的實現(xiàn)是加了一個標(biāo)志位凳兵,記錄地位處理次數(shù),強(qiáng)制轉(zhuǎn)4個B形庭。不過還是推薦這個作者最后的實現(xiàn)方式,
local function varint64_next_byte_h_l(h, l) if h ~= 0 then -- encode lower 28 bits. local b1 = bor(band(l, 0x7F), 0x80) local b2 = bor(band(rshift(l, 7), 0x7F), 0x80) local b3 = bor(band(rshift(l, 14), 0x7F), 0x80) local b4 = bor(band(rshift(l, 21), 0x7F), 0x80) -- merg high 32-bits with the last 4 bits from the low 32-bits l = (h * 16) + band(rshift(l, 28), 0xF) -- Use variable length encoding of higher 36 bits. return b1, b2, b3, b4, varint_next_byte(l) end -- No high bits. Use variable length encoding of low bits. return varint_next_byte(l) end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末旨椒,一起剝皮案震驚了整個濱河市涣仿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钧汹,老刑警劉巖拔莱,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嗤形,居然都是意外死亡赋兵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人橄霉,你說我怎么就攤上這事邑蒋。” “怎么了医吊?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長遮咖。 經(jīng)常有香客問我,道長麦箍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任挟裂,我火速辦了婚禮揍诽,結(jié)果婚禮上诀蓉,老公的妹妹穿的比我還像新娘暑脆。我一直安慰自己,他們只是感情好添吗,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著妓美,像睡著了一般僵腺。 火紅的嫁衣襯著肌膚如雪壶栋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天贵试,我揣著相機(jī)與錄音,去河邊找鬼锡移。 笑死漆际,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的奸汇。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼戳吝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了听哭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤陆盘,失蹤者是張志新(化名)和其女友劉穎败明,沒想到半個月后隘马,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體妻顶,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年幔嗦,在試婚紗的時候發(fā)現(xiàn)自己被綠了沥潭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邀泉。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡叛氨,死狀恐怖棘伴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情焊夸,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布阱穗,位于F島的核電站使鹅,受9級特大地震影響揪阶,放射性物質(zhì)發(fā)生泄漏患朱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一裁厅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧执虹,春花似錦、人聲如沸袋励。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至糠雨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間甘邀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工松邪, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留哨查,地道東北人逗抑。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像邮府,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子褂傀,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容