javascript
新型序列化类库MessagePack,比JSON更快、更小的格式
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,XML又太老土了,就跳過他們倆了,只討論JSON和MessagePack了。
為啥會小?
先大概說下MessagePack 為啥會比JSON小吧,先來段json:
{“name“:”heyue“,”sex“:”\u7537“,”company“:”sina“,”age“:30}?
這個json長度為57字節,但是為了表示這個數據結構(所有標紅色的地方就是他為了表示這個數據結構而不得不添加的),它用了23個字節(就是那些大括號、引號、冒號之類的,他們是白白多出來的)。大家可以去http://json.org/?上看看json的數據標示定義。
換成MessagePack,我只能給大家貼代碼和結果了,38字節:
?| 123456789101112131415161718192021222324 | <?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:57Messagepack:38 //從這里可以看出MessagePack比json少了好多"\u4f55\u8dc3\u65b0\u6d6a"json_str:26MessagePack_str:13 //在UTF-8多字節字符中,MessagePack采用原生態存儲,4個漢字,只用了13字節,比原始的只多了1字節"sina china"json_str:12MessagePack_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的擴展的安裝:
?| 123456 | 可以用PECL的安裝方式:pecl install msgpack也可以編譯源碼安裝:$/path/to/phpize$./configure$make && make install |
使用方法:
?| 12345 | <?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的異同之類的,洗洗睡了…'
from:http://www.heyues.com/messagepack/
總結
以上是生活随笔為你收集整理的新型序列化类库MessagePack,比JSON更快、更小的格式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java泛型学习资料小汇
- 下一篇: MessagePack, Protoco