msgpack


效率:測試

msgpack,json,serialize

打包10000次

長度50,62,87

耗時9,95ms,17.45ms,8.85ms

解包

耗時14.76ms,23.93ms,14.61ms

 

MessagePack 是個什么東東?先來看一段官方的解釋:

MessagePack is an efficient binary serialization format. It lets you exchange data among multiple languages like JSON. But it’s faster and smaller. Small integers are encoded into a single byte, and typical short strings require only one extra byte in addition to the strings themselves.

MessagePack  是一個高效的二進制序列化格式。它讓你像JSON一樣可以在各種語言之間交換數據。但是它比JSON更快、更小。小的整數會被編碼成一個字節,短的字符串僅僅只需要比它的長度多一字節的大小。

官方用一句話總結了這個東東:

It’s like JSON.
but fast and small.

最初研究MessagePack 大概是兩年前了,還開了個講座給大家講MessagePack是個什么東西,大概用在什么場合,它是不是給Javascript用的之類的。但是兩年過去了,由於博客平台老系統太多,以至於這個協議一直沒有能推進使用。后來,redis宣布支持MessagePack格式,以及pintrest等公司,也在積極得使用這個協議進行開發,說明這個格式確實有很多先進性。

MessagePack、protocol buffers、json的速度對比

MessagePack、protocol buffers、json的速度對比

這張圖片是以前MessagePack 官方網站的首頁圖片,數字對比確實很能反映問題,筆者不是很了解protocol buffers,XML又太老土了,就跳過他們倆了,只討論JSON和MessagePack了。

為啥會小?

先大概說下MessagePack 為啥會比JSON小吧,先來段json:

{“name“:”heyue“,”sex“:”\u7537“,”company“:”sina“,”age“:30} 

這個json長度為57字節,但是為了表示這個數據結構(所有標紅色的地方就是他為了表示這個數據結構而不得不添加的),它用了23個字節(就是那些大括號、引號、冒號之類的,他們是白白多出來的)。大家可以去http://json.org/ 上看看json的數據標示定義。

換成MessagePack,我只能給大家貼代碼和結果了,38字節:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
$arr = array ( 'name' => "heyue" , 'sex' => '男' , 'company' => 'sina' , 'age' =>30);
echo "Json:" . strlen (json_encode( $arr )). "\n" ;
echo "Messagepack:" . strlen (msgpack_pack( $arr )). "\n" ;
 
$str = "何躍新浪" ;
echo json_encode( $str ). "\n" ;
echo 'json_str:' . strlen (json_encode( $str )). "\n" ;
echo 'MessagePack_str:' . strlen (msgpack_pack( $str )). "\n" ;
$str = "sina china" ;
echo json_encode( $str ). "\n" ;
echo 'json_str:' . strlen (json_encode( $str )). "\n" ;
echo 'MessagePack_str:' . strlen (msgpack_pack( $str )). "\n" ;
 
?>
 
Json:57
Messagepack:38 //從這里可以看出MessagePack比json少了好多
"\u4f55\u8dc3\u65b0\u6d6a"
json_str:26
MessagePack_str:13 //在UTF-8多字節字符中,MessagePack采用原生態存儲,4個漢字,只用了13字節,比原始的只多了1字節
"sina china"
json_str:12
MessagePack_str:11 //英文字符呢?這個僅僅是比json少了一個引號的大小。

我不能給大家算比例,因為這個得看MessagePack的壓縮算法,MessagePack的核心壓縮方式:

1.true、false 之類的:這些太簡單了,直接給1個字節,(0xc2 表示true,0xc3表示false)

2.不用表示長度的:就是數字之類的,他們天然是定長的,是用一個字節表示后面的內容是什么東東,比如用(0xcc 表示這后面,是個uint 8,用oxcd表示后面是個uint 16,用 0xca 表示后面的是個float 32).

3.不定長的:比如字符串、數組,類型后面加 1~4個字節,用來存字符串的長度,如果是字符串長度是256以內的,只需要1個字節,MessagePack能存的最長的字符串,是(2^32 -1 ) 最長的4G的字符串大小。

4.ext結構:表示特定的小單元數據。

5.高級結構:MAP結構,就是key=>val 結構的數據,和數組差不多,加1~4個字節表示后面有多少個項。

這個是官方的數據表示結構文檔:https://gist.github.com/frsyuki/5432559

總的來說,MessagePack對數字、多字節字符、數組等都做了很多優化,減少了無用的字符,二進制格式,也保證不用字符化帶來額外的存儲空間的增加,所以MessagePack比JSON小是肯定的,小多少,得看你的數據。如果你用來存英文字符串,那幾乎是沒有區別….

為啥會快?

先說說JSON怎么解析吧,我們開發中一般都用cJSON這個庫,cJSON存儲的時候是采用鏈表存儲的,其訪問方式很像一顆樹。每一個節點可以有兄妹節點,通過next/prev指針來查找,它類似雙向鏈表;每個節點也可以有孩子節點,通過child指針來訪問,進入下一層。問題就是首先,構造這個鏈表的時候,得一個字符一個字符地匹配過去吧,得判斷是不是引號、括號之類的吧…

但是MessagePack 則簡單多了,直接一遍遍歷過去了,從前面的數據頭,就可以知道后面的是什么數據,指針應該向后移動多少,比JSON的構建鏈表少了很多比較的過程。

來計算個數據吧,把剛才的數組,encode、decode重復1000萬次:

msgpack_unpack(msgpack_pack($arr));

json_decode(json_encode($arr));

Json:37.099s

MessagePack:22.050s

大概是快這么多吧,如果數組更大,理論上,MessagePack比Json快更多。

MessagePack的常用的地方:

MessagePack 不是給JS用的,雖然它有JS的庫,但是用瀏覽器來解析MessagePack是一件很悲劇的事情,我曾經測試過(如果我還能找到,我會提供代碼),在低端瀏覽器下,JS計算MessagePack會卡死在那里,畢竟JSON是javascript親生的,用起來自然比MessagePack要容易。

MessagePack主要用於結構化數據的緩存和存儲:

1.存在Memcache中,因為它比json小,可以省下一些內存來,速度也比json快一些,頁面速度自然快一個檔次。當然,也有一種情況,我在mc中存json,然后直接出來就是頁面可用的json,都不用解析json了(當然這個在實際開發中比較少見)。

2.存在可以持久化的Key-val存儲中。

MessagePack的現狀:

我就說PHP吧,因為C、C++的沒啥好說的,就是解包、打包,速度比JSON快一些,但是業務邏輯的數據太多,還是先考慮上層的吧。

PHP的MessagePack的擴展的安裝:

?
1
2
3
4
5
6
可以用PECL的安裝方式:
pecl install msgpack
也可以編譯源碼安裝:
$ /path/to/phpize
$. /configure
$ make && make install

使用方法:

?
1
2
3
4
5
<?php
$data = array (0=>1,1=>2,2=>3);
$msg = msgpack_pack( $data );
$data = msgpack_unpack( $msg );
?>

這個MessagePack的PHP擴展,是傳說中的鳥哥Laruence開發維護的,在鳥哥的Yar中,也使用了MessagePack 作為打包協議之一。

從現狀看來,MessagePack目前還很少有公司大規模使用?這是為什么呢?由於沒有讀過MessagePack的相關的源碼,所以在這個范疇,鳥哥最有發言權…

后來,redis 2.6支持了MessagePack…

先寫到這里了,有空了,再補充一些,比如MessagePack 和 protocol buffer的異同之類的,洗洗睡了…


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM