性能超四倍的高性能.NET二進制序列化庫

二進制序列化在.NET中有不少使用場景,如咱們使用分佈式緩存時,一般將緩存對象序列化爲二進制數據進行緩存,在ASP.NET中,不少中間件(如認證等)也都是用了二進制序列化。git

在.NET中咱們一般使用System.Runtime.Serialization.Formatters庫中的BinaryFormatter來進行二進制序列化,但此庫存在如下缺點:github

  • 儘管.net core對BinaryFormatter進行了一些列優化,但其性能仍是較低
  • 序列化結果尺寸過大,BinaryFormatter保留了很是詳細的類型元數據。
  • 安全問題,BinaryFormatter 由於其強大的功能和易用性而普遍用於整個 .NET 生態系統。 可是,其強大的功能也讓攻擊者可以影響目標應用內的控制流。 成功的攻擊可能致使攻擊者可以在目標進程的上下文中運行代碼。(可參考此文檔
  • 經過AssemblyLoadContext動態加載程序集可能沒法反序列化的問題(好比使用[PluginFactory]插件框架),例如,你在公共庫A中封裝了序列化輔助方法,在插件程序集B中聲明瞭序列化類型,並經過公共庫A中的輔助方法進行序列化或反序列化,最後主程序集C經過獨立的AssemblyLoadContext動態加載插件程序集B,此種場景中,B中反序列化時將會引起沒法找到程序集的異常。
  • 序列化類,必須經過SerializableAttribute特性進行標註

爲了解決這些缺陷,咱們開源了一款獨立的高性能.NET二進制序列化庫Xfrogcn.BinaryFormatter([Github]  [Gitee]),該庫參考了System.Text.Json庫,經過Span與Emit大大提高了序列化性能。此庫目標爲.NET Standard 2.1。數組

Xfrogcn.BinaryFormatter具備如下優勢:緩存

  • 高性能,經過Span與Emit大大提高了性能,其性能超過System.Runtime.Serialization.Formatters庫的近四倍
  • 更小的序列化尺寸(75%)
  • 簡單易用,與System.Text.Json基本一致的API接口。
  • 反序列化時實例引用的維持
  • 類型元數據保留,無需在反序列化時指定目標類型
  • 支持反序列化到不一樣的類型
  • 更安全
  • 支持AssemblyLoadContext動態加載程序集中類型的序列化
  • 無需SerializableAttribute特性標註
  • 完善的內置類型支持([支持的類型])

1、性能

與.NET內置的System.Runtime.Serialization.Formatters.Binary.BinaryFormatter二進制序列化對比,性能最高可達到它的4倍以上,而序列化結果的大小僅只有它的75%。安全

如下爲經過test/BinaryFormatter.Benchmark性能測試項目獲取的性能數據,其中:框架

  • Json指System.Text.Json,能夠看到其性能的確強悍
  • XfrogcnBinary指本庫
  • SystemBinaryFormatter指.NET內置二進制序列化庫(System.Runtime.Serialization.Formatters.Binary.BinaryFormatter)
  • 類別Stream爲採用流化方式序列化
  • 類別Bytes爲直接序列化爲Byte數組或從Byte數組反序列化 全部的測試都基於默認配置,(流化方式下默認的緩衝區大小將會明顯影響序列化性能)

序列化

序列化

Method Categories Mean
Json Stream 61.41 μs
XfrogcnBinary Stream 92.97 μs
SystemBinaryFormatter Stream 291.37 μs
Json_Bytes Bytes 59.79 μs
XfrogcnBinary_Bytes Bytes 88.67 μs

 

反序列化

反序列化

Method Categories Mean
Json Stream 100.12 μs
XfrogcnBinary Stream 96.34 μs
SystemBinaryFormatter Stream 334.68 μs
Json_Bytes Bytes 80.13 μs
XfrogcnBinary_Bytes Bytes 92.14 μs

 

2、如何使用

Xfrogcn.BinaryFormatter庫的使用很是簡單,基本與System.Text.Json一致:分佈式

序列化

序列化到流:ide

MemoryStream ms = new MemoryStream();
await Xfrogcn.BinaryFormatter.BinarySerializer.SerializeAsync(ms, data);

序列化到byte數組:性能

var data = Xfrogcn.BinaryFormatter.BinarySerializer.Serialize(data);

反序列化

從流中反序列化:測試

var obj = await Xfrogcn.BinaryFormatter.BinarySerializer.DeserializeAsync(stream);

從byte數組反序列化:

var obj = Xfrogcn.BinaryFormatter.BinarySerializer.Deserialize(data);

反序列化爲指定類型:

var obj = await Xfrogcn.BinaryFormatter.BinarySerializer.DeserializeAsync<T>(stream);
或者:
var obj = Xfrogcn.BinaryFormatter.BinarySerializer.Deserialize<T>(data);

固然,你也能夠在序列化與反序列化時指定不一樣的配置(),更詳細的使用說明請參考[快速開始]

3、注意事項

  • 與System.Text.Json的設計一致,因爲類型解析、序列化轉換器等緩存都是以配置實例爲基礎,即每個配置實例的緩存是獨立的,故請使用共享的配置實例,請勿爲每一次序列化分配新的配置實例
  • 在流模式下,默認緩衝區的大小會極大地影響讀取性能,請根據實際狀況進行詳細的測試以獲取合適的緩衝區設置(默認設置可適合大多數場景)

 

開源須要你們的努力,有興趣的同窗,歡迎提交代碼,一塊兒完善!

相關文章
相關標籤/搜索