一次失敗的protobuf基準測試

2021-08-27 12:35:10 字數 2180 閱讀 5333

之前看到pemelo資料的時候,作者曾提到對pemolo的一次優化,json的完全序列化成為伺服器訊息**的乙個瓶頸. 目前我的遊戲伺服器中使用了protocbuf作為協議, 它的表現很穩定.讓客戶端和我對於協議的交流很流暢,極大的提高了兩邊的開發效率. 看起來很完美.但我總隱隱的覺得不安. 我有時候會懷疑:

目前的protobuf的方式會不會有問題.會不會讓伺服器的對協議物件的序列化和反序列化成為伺服器的效能瓶頸. 

由於我們遊戲的訊息型別比較多,大概有100種請求,為了方便對訊息的序列/反序列化的操作.一般會使用乙個大訊息  包裹  子訊息的方式來組織:

根據protobuf的官方文件描述了一種union type的組織形式來實現(

message onemessage 

required type type = 1;

optional foo foo = 2;

optional bar bar = 3;

optional baz baz = 4;

}

而在google group對此需求的討論中,有人提出了內嵌訊息位元組流的方式:

message onemessage 

required type type = 1;

required bytes innermessage = 2;

}

我最終採用了後乙個方法.因為我覺得前者會有三個缺點:

1. 大訊息體過於冗長,對於乙個子訊息型別可能有幾百種的專案來說,很難維護

2. 訊息中的可選訊息欄位過多.但都為null,每個被序列化後的訊息會占用很多無用的引用記憶體.而訊息物件的數量又恰恰是數量最為龐大.可能會有隱患.

3. 內嵌物件不是每次都需要序列化. 伺服器儲存了對話的狀態,每種狀態只能傳送型別的報文.如果客戶端改善的報文型別和伺服器狀態不對應.則可以直接丟棄報文.無必要序列化內部訊息.

就這樣,專案穩定的執行了一段時間,但偶然的一次debug, 發現protbuf的內部**對內部訊息的序列存在乙個效能隱患:

像protobuf中對位元組的定義:  required bytes innermessage = 2;

probobuf在序列化的時候,都會轉化為不變的bytestring物件,但在生成bytestring物件時, 會對原始的訊息位元組陣列進行一次拷貝,再傳遞給序列化後的物件(參見codedinputstream.readbytes()). 

雖然protbuf對位元組陣列的拷貝使用是system.arraycopy(native的 memcopy).但從功能上來說,這樣的拷貝對於我來說,完全沒有必要(google groups有人同樣對此產生了懷疑 

相對於一次性序列化的union type方式,使用內嵌訊息位元組流的方式,會多做一次位元組陣列的拷貝.我很擔心這樣會產生效能問題.

於是為了比較這兩種方式.我做了乙個簡單的基本測試.

message pbtestnestpacket 

message pbtestunionpacket

生成了兩種內容同樣的訊息,並分別生成訊息序列化後的位元組陣列, 然後對兩個不同的位元組陣列深度序列化.

各自執行不同的幾組測試,結果發現兩種方式的響應時間並無太大差異,在多數時候,巢狀位元組陣列的方式.響應時間更快.

報文大小     測試輪數      內嵌方式響應時間   union方式響應時間.

report: size:20, testturn:5000 : nest: 167 union: 216

report: size:100, testturn:5000 nest 246 union 256

report: size:100, testturn:50000 nest 1163 union 1236

report: size:500, testturn:5000 nest 750 union 789

report: size:500, testturn:50000 nest 10122 union 10129

report: size:1000, testturn:5000 nest 1407 union 1421

report: size:5000, testturn:5000 nest 9471 union 9690

雖然產生了不科學的結果,但這次測試至少讓我自己放了心.目前的使用協議方式和另一種方式相比效能上沒有劣勢.維護性上提高了不少.

一次失敗的聚會

十一長假,無處可去,也哪兒也不想去。正家中閒坐,同學邀請明日去森林公園一遊,欣然點頭。轉過身來,妻子轉告 朋友們明天森林公園聚會。女怕撞衫,男怕撞席。不自覺中,我變成了鏈結兩個party的關鍵人物。10點,三個it家庭會面。開始吃吃喝喝,順便談談子女教育。11點,兩個媽媽帶著孩子過來,話題開始散亂。...

一次失敗的面試

做任何毫不費力的事情,都是在浪費時間,忘記這是哪本書裡看到的了,到了30歲的年紀,越來越有感觸,記錄失敗的面試,順便祭奠一下被我揮霍掉的這5年。前提 公司從事的行業就不透露了,主要從事一些內部專案,如流程管理,原素材管理等。專案很多,但都不是很大,工作壓力不是很大,只要多了解業務,思路清晰,很多任務...

一次失敗的騎行

不得不說這是一次失敗的騎行,因為我後悔了!原始計畫是這樣的 路線 南京 上海 裝備 山地車 景點 好好欣賞下南京到上海的每乙個城市 但。事實情況是這樣的 上午我還在圖書館看書,中午我突然想出發了,我就收拾東西回宿舍收拾東西,山地車我還沒來得及買,那就用我的小破自行車將就一下吧,隨便收拾了下我就去實驗...