性能超四倍的高性能.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的设计一致,因为类型解析、序列化转换器等缓存都是以配置实例为基础,即每个配置实例的缓存是独立的,故请使用共享的配置实例,请勿为每一次序列化分配新的配置实例
  • 在流模式下,默认缓冲区的大小会极大地影响读取性能,请根据实际状况进行详细的测试以获取合适的缓冲区设置(默认设置可适合大多数场景)

 

开源须要你们的努力,有兴趣的同窗,欢迎提交代码,一块儿完善!

相关文章
相关标签/搜索