進入在學習redis的時候,在文中看到了關於MessagePack的簡介,發現非常有意思,於是就花了點時間大致瞭解了下。 MessagePack介紹: MessagePack is an efficient binary serialization format.It lets you exchan ...
進入在學習redis的時候,在文中看到了關於MessagePack的簡介,發現非常有意思,於是就花了點時間大致瞭解了下。
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更快、更小。小的整數會被編碼成一個位元組,短的字元串僅僅只需要比它的長度多一位元組的大小
支持語言:
MessagePack is supported by over 50 programming languages and environments.
MessagePack和JSON壓縮後文件比較
這張圖片是以前MessagePack 官方網站的首頁圖片,數字對比確實很能反映問題,這裡只討論JSON和MessagePack了
為啥會小呢?先來段json:
{“name“:”heyue“,”sex“:”\u7537“,”company“:”sina“,”age“:30}
這個json長度為57位元組,但是為了表示這個數據結構(所有標紅色的地方就是他為了表示這個數據結構而不得不添加的),它用了23個位元組(就是那些大括弧、引號、冒號之類的,他們是白白多出來的)。
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的構建鏈表少了很多比較的過程
MessagePack主要用於結構化數據的緩存和存儲:
1.存在Memcache中,因為它比json小,可以省下一些記憶體來,速度也比json快一些,頁面速度自然快一個檔次。當然,也有一種情況,我在mc中存json,然後直接出來就是頁面可用的json,都不用解析json了(當然這個在實際開發中比較少見)。
2.存在可以持久化的Key-val存儲中。
.NET使用
1.從GIT https://github.com/msgpack/msgpack-cli.git上下載源碼編譯生成DLL
2.示例
using System.IO; using MsgPack.Serialization; namespace MsgPack { class Program { static void Main(string[] args) { CreateMsgPack(); } static void CreateMsgPack() { WriteToFile(); ReadFromFile(); using (var stream = new MemoryStream()) { var serializer = MessagePackSerializer.Create<Person>(); serializer.Pack(stream, CreateIris()); stream.Position = 0; var person = serializer.Unpack(stream); } } static void WriteToFile() { var serializer = MessagePackSerializer.Create<Person>(); using(Stream stream = File.Open(@"C:\Users\Iris\msg.txt", FileMode.Create)) { serializer.Pack(stream, CreateIris()); } } static void ReadFromFile() { var serializer = MessagePackSerializer.Create<Person>(); using (Stream stream = File.Open(@"C:\Users\Iris\msg.txt", FileMode.Open)) { var iris = serializer.Unpack(stream); } } static Person CreateIris() { return new Person { Age = 28, Name = "Iris Classon", FavoriteNumbers = new[] {2,3,4} }; } } public class Person { public string Name { get; set; } public int Age { get; set; } public int[] FavoriteNumbers { get; set; } } }