2021-01-11

博客园Logo
首页
新闻
博问
专区
闪存
班级
代码改变世界
搜索
注册
登录
返回主页
xfrog
让技术带着创意飞翔…
博客园首页新随笔联系订阅管理随笔 - 31 文章 - 0 评论 - 194
性能超四倍的高性能.NET二进制序列化库
二进制序列化在.NET中有很多使用场景,如我们使用分布式缓存时,通常将缓存对象序列化为二进制数据进行缓存,在ASP.NET中,很多中间件(如认证等)也都是用了二进制序列化。

在.NET中我们通常使用System.Runtime.Serialization.Formatters库中的BinaryFormatter来进行二进制序列化,但此库存在以下缺点:

尽管.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特性标注
完善的内置类型支持([支持的类型])
一、性能
与.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

二、如何使用
Xfrogcn.BinaryFormatter库的使用非常简单,基本与System.Text.Json一致:

序列化
序列化到流:

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(stream);
或者:
var obj = Xfrogcn.BinaryFormatter.BinarySerializer.Deserialize(data);
当然,你也可以在序列化与反序列化时指定不同的配置(),更详细的使用说明请参考[快速开始]

三、注意事项
与System.Text.Json的设计一致,由于类型解析、序列化转换器等缓存都是以配置实例为基础,即每一个配置实例的缓存是独立的,故请使用共享的配置实例,请勿为每一次序列化分配新的配置实例
在流模式下,默认缓冲区的大小会极大地影响读取性能,请根据实际情况进行详细的测试以获取合适的缓冲区设置(默认设置可适合大多数场景)

开源需要大家的努力,有兴趣的同学,欢迎提交代码,一起完善!

标签: Serialization, .NET
好文要顶 关注我 收藏该文
xfrog
关注 - 2
粉丝 - 207
推荐博客
+加关注
10
« 上一篇: 一个.NET Core下的开源插件框架
posted @ 2021-01-11 10:57 xfrog 阅读(364) 评论(3) 编辑 收藏

评论列表
#1楼 2021-01-11 11:06 八面威风
为何不直接用System.Text.Json呢?

支持(0) 反对(0)
#2楼 2021-01-11 11:06 czd890
考虑和mesagepack, protobuf 之类的进行比较.
同时要多维度比较, 比如CPU, GC, 内存分配等.

支持(1) 反对(0)
#3楼 2021-01-11 12:13 yahle
能兼容原生的BinaryFormatter序列化和反序列化出来的数据吗?

支持(0) 反对(0)
刷新评论刷新页面返回顶部
登录后才能发表评论,立即 登录 或 注册, 访问 网站首页
【推荐】阿里出品,对标P7!限时免费,七天深入MySQL实战营报名开启
【推荐】大型组态、工控、仿真、CADGIS 50万行VC++源码免费下载
【推荐】AWS携手博客园为开发者送福利,注册立享12个月免费套餐
【推荐】第一个NoSQL数据库,在大规模和一致性之间找到了平衡
【推荐】七牛云新老用户同享 1 分钱抢 CDN 1TB流量大礼包!
【推荐】了不起的开发者,挡不住的华为,园子里的品牌专区
【推荐】未知数的距离,毫秒间的传递,声网与你实时互动

相关博文:
· 超燃| 2019 中国.NET 开发者峰会视频发布
· C++/CLI调用Net类库
· mysql 数据库优化,分表超作
· 超燃:2019 中国.NET 开发者峰会视频发布
· 命令创建.net core3.0 web应用详解(超详细教程)
» 更多推荐…

最新 IT 新闻:
· 能刷好评也能删差评 大众点评变味了?
· 前懂球帝CTO许立强日前正式加入字节跳动 曾担任百度主任架构师
· 82万的新车一月连撞两车 女司机称刹车失灵!特斯拉:你去告我们
· 比宝马5系贵2万多!秦力洪:蔚来ET7订单达预期 不会降价
· 泄露代码曝光Windows 10 21H2 RTM完成时间:今年最重大版本
» 更多新闻…
公告
昵称: xfrog
园龄: 10年10个月
荣誉: 推荐博客
粉丝: 207
关注: 2
+加关注
搜索

常用链接
我的随笔
我的评论
我的参与
最新评论
我的标签
我的标签
MVC(10)
WCF(8)
C#(7)
.NET(3)
JavaScript(2)
LINQ(2)
Silverlight(2)
SQL Server(2)
Plugin(1)
Serialization(1)
更多
积分与排名
积分 - 58130
排名 - 17800
随笔档案
2021年1月(1)
2020年11月(1)
2013年6月(1)
2013年5月(1)
2012年3月(1)
2011年7月(1)
2011年2月(1)
2011年1月(5)
2010年12月(4)
2010年10月(2)
2010年9月(3)
2010年6月(2)
2010年5月(7)
2010年4月(1)
链接
转到旧博客
最新评论

  1. Re:性能超四倍的高性能.NET二进制序列化库
    能兼容原生的BinaryFormatter序列化和反序列化出来的数据吗?

–yahle
2. Re:性能超四倍的高性能.NET二进制序列化库
考虑和mesagepack, protobuf 之类的进行比较.
同时要多维度比较, 比如CPU, GC, 内存分配等.

–czd890
3. Re:性能超四倍的高性能.NET二进制序列化库
为何不直接用System.Text.Json呢?

–八面威风
4. Re:WCF编程系列(一)初识WCF
期待

–純眞發酵
5. Re:一个.NET Core下的开源插件框架
这个又什么用途,应用场景是什么?

–王金虎
阅读排行榜

  1. 一个.NET通用JSON解析/构建类的实现(c#)(80604)
  2. SQL Server 2008中的CTE递归查询(38576)
  3. Linq(筛选与排序)(37467)
  4. WCF编程系列(一)初识WCF(11545)
  5. MVC中的扩展点(六)ActionResult(9606)
    评论排行榜
  6. 一个.NET通用JSON解析/构建类的实现(c#)(35)
  7. WCF编程系列(一)初识WCF(15)
  8. SQL Server 2008中的CTE递归查询(13)
  9. 如何编写Windows服务(11)
  10. MVC中的扩展点(一)路由系统简介(9)
    推荐排行榜
  11. SQL Server 2008中的CTE递归查询(17)
  12. WCF编程系列(一)初识WCF(14)
  13. 一个.NET Core下的开源插件框架(10)
  14. 一个.NET通用JSON解析/构建类的实现(c#)(10)
  15. 创建Silverlight 5浏览器内受信应用(8)
    Copyright © 2021 xfrog
    Powered by .NET 5.0 on Kubernetes
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个获取当前日期时间,并将它以“XXXX年XX月XX日 hh:mm:ss”的格式输出打印的示例代码: ```java import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; public class DateUtils { // 获取当前日期时间,并将它以“XXXX年XX月XX日 hh:mm:ss”的格式输出打印 public static void showCurrentDateTime() { DateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); Date date = new Date(); String dateTime = dateFormat.format(date); System.out.println(dateTime); } // 计算并显示若干天后的日期值 public static void showDateAfterDays(String currentDate, int days) { DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); try { Date date = dateFormat.parse(currentDate); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.DAY_OF_YEAR, days); Date newDate = calendar.getTime(); String newDateString = dateFormat.format(newDate); System.out.println(newDateString); } catch (ParseException e) { e.printStackTrace(); } } // 计算并显示两个日期之间相距的天数 public static void showDaysBetweenDates(String date1, String date2) { DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); try { Date startDate = dateFormat.parse(date1); Date endDate = dateFormat.parse(date2); long diff = endDate.getTime() - startDate.getTime(); long diffDays = diff / (24 * 60 * 60 * 1000); System.out.println(diffDays); } catch (ParseException e) { e.printStackTrace(); } } } ``` 使用示例: ```java public static void main(String[] args) { // 获取当前日期时间,并将它以“XXXX年XX月XX日 hh:mm:ss”的格式输出打印 DateUtils.showCurrentDateTime(); // 计算并显示若干天后的日期值 DateUtils.showDateAfterDays("2021-01-01", 10); // 计算并显示两个日期之间相距的天数 DateUtils.showDaysBetweenDates("2021-01-01", "2021-01-11"); } ``` 输出结果: ``` 2021年05月01日 15:23:45 2021-01-11 10 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值