1. 程式人生 > >MessagePack 新型序列化反序列化方案

MessagePack 新型序列化反序列化方案

only program next sel ges new sys adf 簡介

進入在學習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、protocol buffers、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; }
}
}

  

MessagePack 新型序列化反序列化方案