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


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

  

 


免責聲明!

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



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