[.NET 开源] 高性能的 Swifter.MessagePack 已发布,并附带新版本的 Swifter.Json 和 Swifter.Data。
抱歉各位朋友,由于各种私事公事,本应该在 19 年底发布的 Swifter.MessagePack 库延迟了这么久才发布,我深感抱歉。
MsgPack 简介
MsgPack 一种非常轻巧的二进制数据交换格式,巧妙的设计让它相比其他二进制数据格式更可读,并且有着不错的压缩率和逻辑性能,是目前相当火热的数据交换格式。
Swifter.MessagePack 遵循 MsgPack 新的规范实现;相比 .NET 其他 MsgPack 序列化库,Swifter.MessagePack 有着更好的性能,生成的内容更紧凑合理且更简单易用。
Nuget:Swifter.MessagePack,Swifter.Json,Swifter.Data
GitHub:Swifter.MessagePack,Swifter.Json
如果您想使用 Swifter 库,请在 Nuget 上安装/下载最新版本,如需单文件版本,请自行生成/合并。
简单使用 Swifter.MessagePack
MessagePackFormatter 类内部还有数十个方法重载,包括静态和实例方法,总有一些适合您;这些方法都是线程安全的。
更多使用方法请参考早期关于 Swifter.Json 的文章,GitHub 或 Wiki;学习交流进 Swifter 的 QQ 群:133630914(新群,欢迎加入)。
Swifter 框架的特性
(1) Swifter 可以运行在 .NET Framework 2.0+, .NET Core 2.0+, .NET Standard 2.0+, MONO JIT, MONO AOT, Xamarin.Android, Xamarin.iOS, Unity JIT 等平台/运行时上,Unity IL2CPP 运行时由于没有我们测试环境,不知可否正常运行,更多信息请看下面的 AOT 说明。
(2) Swifter 有着深层的抽象封装,这虽然带来了一些性能和内存的损耗,但也获得了更高的扩展性;Swifter.Json/Swifter.MessagePack/Swifter.Data 的可公用的代码非常多,这使得在 Swifter 上实现一个新的序列化库只需要编写少量代码即可实现,这是其他框架难实现的。
(3) 虽然 Swifter 有很多接口和抽象编程,但是 Swifter 并没有因此比其他的框架慢或内存占用大,反比它们更快和更小内存占用;这是因为 Swifter 从来都是使用更好算法和逻辑来获取性能,而不是使用更直接的代码获取直接的性能。
(4) 作为类库开发者,我们深知每个人开发和测试的侧重点都与他人不一样,自己找出自己的问题太难,所以 Swifter.Json 和 Swifter.MessagePack 除了我们自己的测试单元之外, 还 "偷" 了 Newtonsoft, Neuecc 和 Spanjson 的 5000+ 个测试单元( 去除了 Newtonsoft 的部分测试单元);现已测试通过 4200+ 个,不通过 800+ 个是我们认为可以允许或是更加合理的行为。(不劳而获的测试单元确实用着很爽,但事实是我们"搬"这些测试单元用了 3 天,无脑替换改到手指抽筋)
Swifter.Json 和 Swifter.MessagePack
(1) Swifter.MessagePack 和 Swifter.Json 一样,都有着非常优异的性能和极小的额外内存分配。
(2) Swifter.MessagePack 和 Swifter.Json 的 API 大致相同,如果使用者同时使用它们,那么可以极小成本在它们之间切换。
(3) 得益于 Swifter.Core 的强大数据映射,Swifter.MessagePack 和 Swifter.Json 都同时支持 .NET 上大多数常用的数据结构和类型。
(4) Swifter.MessagePack 和 Swifter.Json 对重复引用的对象的表示方式不一样,在开启 MultiReferencingReference 配置项后,Swifter.Json 将使用 { "$ref": "#/obj/1/target" } 来表示重复引用的对象,而 Swifter.MessagePack 使用对象在 MsgPack 内容的偏移量表示重复引用的对象;相比之下 Swifter.MessagePack 的方案更简单性能更快,但是可读性较差,不过说来 MsgPack 本来就是要专门的工具才能阅读。
(5) Swifter.MessagePack 在序列化基础类型时,在保证精度不丢失的前提下,将大数据类型转换为更小数据类型,以得到更紧凑的 MsgPack 内容(如将 double 123 转换为 int 123,int 123 只需要 1 个字节即可表示,如果不做转换则需要 9 个字节表示)。
(6) Swifter.MessagePack 在序列化未知长度的集合时(如 Enumerable<T>),会将长度定义为四字节 (FixArray32),然后在写入完成后把实际长度赋予这四字节长度;这样虽然在较短的未知长度集合时,将产生 1-3 个 0;但是这避免了将未知长度的集合转换为 List<T> 或 T[], 这提高了性能也减少了内存分配,这是不亏的(因为未知长度的集合很常用,如 Linq,DbDataReader 等)。
新版本做了啥?
(1) 主要是解决了已知 BUG,包括了 Issues 上提到的几个。
(2) 允许将 "" 值解析为 DateTime, int?, double 等基础类型的默认值,但是需要启用 EmptyStringAsDefault 配置项,默认未开启。
(3) 解决了 Swifter.Json 浮点数: float, double 失真的问题,并增加了 UseSystemFloatingPointsMethods 配置项使用系统的浮点数方法,此配置项的更多说明请看该配置项的注释。
(4) 增加了序列化的事件:ObjectFiltering 和 ArrayFiltering,这两个事件可以对正在序列化中的 键/值 做处理和筛选,包括驼峰命名法,忽略一些值等。它们被放在 JsonFormatter 和 MessagePackFormatter 的实例里面。
(5) 增加了 .NET 对象的持久序列化和反序列化功能,这个功能将对象序列化为包含类型信息和字段值的内容,不包含逻辑信息;使用 SerializationBox<T> 盒子使用此功能。图示:
更多新增的功能请继续看以下内容。
AOT
在 Swifter 新版本里,AOT 的 JIT 的界限更加明显,由 VersionDifferences.IsSupportEmit 字段标识;当这个字段为 true 表示当前平台是 JIT 运行时,Swifter 将在一些类中使用 Emit 技术提高性能;当此字段为 false 时,Swifter 会完全不使用 Emit 技术。
因我们设备有限,无法提供大规模的平台测试,但我们非常希望可以 Swifter 可以支持更多的平台,所以希望朋友们加 Swifter 交流 QQ 群:(133630914),在这里我们可以更快的提供反馈。
直接文档读取/写入的 API
通常情况下,将小型对象序列化为 Json/MsgPack 和将小型 Json/MsgPack 反序列化为对象是 .NET 程序中常见的操作,Swifter 也正以此为常用场景做优化,所以 Swifter 在对小型数据操作时性能最佳,且相比其他 Json/MsgPack 解析库优势明显。
但在大型数据下优势减少,这主要原因是大型数据的存储需要实体类或字典/集合存储,创建/填充/遍历这些对象消耗了大量资源(接口编程的损耗);所以 Swifter 提供了直接读取/写入的 API 来绕开了对存储介质的操作,以更快更小损耗的读写大型数据。
使用 JsonFormatter.CreateJsonReader/MessagePackFormatter.CreateMessagePackReader 函数来创建文档读取器,使用 JsonFormatter.CreateJsonWriter/MessagePackFormatter.CreateMessagePackWriter 函数来创建文档写入器。
使用文档读取器完整的读取一个 Json/MsgPack 文档将比反序列化为对象快 4-8 倍!使用文档写入器生成文档的性能与将实体类序列化为 Json/MsgPack 相差较小,前提是您已构建好了这些对象。
读取器演示:
写入器演示:
拥有简单预测数组的长度的能力
Swifter 在对小型数组,部分集合写入时,会根据数组的类型,来源(Data,Json,MsgPack 等),名称等信息并结合之前的一些长度记录,简单的预测出新的数组的长度;在写入完成后,如果预测长度与实际长度不符,则扩展或压缩为实际长度;如果与实际长度相符,则不需要重新创建新数组。此能力有效提高反序列化小型数组和部分集合性能,并且减少额外内存分配。
在其他高性能的 Json 解析库,它们使用 ArrayPool<T> 同样可以提高性能和减少内存分配;但是由于 Swifter 对兼容性的要求,使得我们不能使用 ArrayPool<T> 方案;在数组的长度比较稳定的情况下,我们的方案更好;但在数组长度非常不稳定的情况下,我们的方案可能仍需要 1-3 次的扩容/压缩。
假定有序的对象反序列化
Swifter.Json 和 Swifter.MessagePack 都支持了假定有序的对象反序列化,当一个 Json/MsgPack 的对象与当前的实体类对象的字段顺序一致时,将有效提升反序列化性能。
此操作默认不开启,可以使用 AsOrderedObjectDeserialize 配置项开启。
高性能的反射封装
Swifter.Core 里提供了一些对反射封装的类,它们放在 Swifter.Reflection 命名空间下;这些类型主要功能就是提高了系统反射的性能;XObjectRW 正是使用它们实现不依赖 Emit 的高性能对象读写器。
虽然放弃一些安全性检查可以提高更多的性能,但是我们并没有这么做;我们仍然有类型安全检查和防溢出检查(事实上读写字段和属性大多数的损害都在这里,如果去掉这些检查将得到上百倍的性能;事实上这些检查只起到了提示程序员不能这么做的作用,程序实际运行时这些检查无意义)。
高效的数字 ToString 和 Parse 方法
Swifter.Core 提供了一些高性能数字算法,包括 Int64, UInt64, Double, Single, Decimal 的 Parse 和 ToString 算法,它们被放在 Swifter.Tools.NumberHelper 里,这些算法被应用与 Swifter.Json 和一些其他地方,这些算法支持 2-64 进制。
XConvert 万能类型转换器
Swifter.Tools.XConvert.Convert<TSource, TDestination> 是一个功能强大的万能类型转换函数,它在初始化时尝试以下方式获取合适的转换函数:
(1) 包含在 System.Convert 里的基础转换函数;
(2) 类型兼容的隐式转换(如:从子类转换为父类,从 Int32 转换为 Int64,从 Int64 转换为 Double)。
(3) 原类型和目标类型中的 static implicit operator (隐式转换) 函数。
(4) 原类型中的 ToXXX 实例函数。
(5) 目标类型中的 Parse 和 ValueOf 静态函数。
(7) 目标类型的构造函数。
(8) 原类型和目标类型中的 static explicit operator (显式转换) 函数。
(9) 当以上方法都没有找到合适函数时,将使用 (TDestination)(object)value 进行强制转换。
简单示例:
性能测试
ServiceStack.Json, Jil, LitJson, NetJson 等库因为出错太多未展示出来;如果有需要,您可以到 GitHub 上自行克隆/修改/运行,已收录了 .NET 的大多数 Json 序列化库。
更多实用功能等你发现...
Swifter.Core 还提供了许许多多的工具类,包括反射,委托,类型转换,字符串,加密,哈希,数字,日期,数组和集合等工具,它们被放在 Swifter.Tools 命名空间下,您可以使用它们来提高开发效率和运行效率。
Swifter.RW 命名空间是整个 Swifter 框架的核心,它主要逻辑是:从读取器中读取值,写入到写入器中;如:从 JsonReader 读取值到 ObjectWriter 或 DictionaryWriter 中;熟悉它们就等于精通了 Swifter 框架。
Swifter.Json/Swifter.MessagePack 有一个非常重要的配置项 JsonFormatterOptions/MessagePackFormatterOptions;使用前建议先阅读它们,以配置更适合您系统的序列化和反序列化方案。
...
最后附上 Swifter.Data 的简介
Swifter.Data 是一个小型的 ORM 工具,它相比 Dapper 性能要快一些,功能要强大一些。
感谢阅读
[.NET 开源] 高性能的 Swifter.MessagePack 已发布,并附带新版本的 Swifter.Json 和 Swifter.Data。的更多相关文章
- 上周 GitHub 热点速览 vol.07:GitHub 官方 CLI beta 版已发布
摘要:GitHub Trending 上周看点,GitHub 官宣 CLI 已发布 beta 版,前端新晋高性能打包神器 esbuild 宣战 Webpack&Parcel,微软.Facebo ...
- 开源版本PowerShell Core 6.2 发布
导读 PowerShell Core 6.2 GA 已发布,PowerShell Core 是 PowerShell 的开源版本,适用于 Linux,macOS 和 Windows. 有关 Power ...
- swoole-1.7.18 版本已发布,支持 PHP7
swoole-1.7.18 版本已发布,支持 PHP7 matyhtf 发布于: 2015年07月23日 (22评) 分享到: 收藏 +16 3月19日,深圳源创会火热报名中,go>> ...
- FreeSql 新手上路系列教程已发布在 cnblogs
FreeSql 是一个功能强大的对象关系映射程序(O/RM),支持 .NETCore 2.1+ 或 .NETFramework 4.5+(QQ群:4336577) FreeSql采用MIT开源协议托管 ...
- FastDFS是使用c语言编写的开源高性能分布式文件系统
FastDFS是什么 FastDFS是使用c语言编写的开源高性能分布式文件系统 是由淘宝开发平台部资深架构师余庆开发,FastDFS孵化平台板块 他对文件进行管理,功能包括文件存储,文件同步,文件访问 ...
- php大力力 [045节] 兄弟连高洛峰 PHP教程 2014年[已发布,点击下载]
http://www.verycd.com/topics/2843130/ 第1部分 WEB开发入门篇第1章LAMP网站构建1.[2014]兄弟连高洛峰 PHP教程1.1.1 新版视频形式介绍[已发布 ...
- 开源搜索引擎Iveely 0.8.0发布,终见天日
这是一篇博客,不是,这是一篇开源人的心酸和喜悦,没有人可以理解我们的心情,一路的辛酸一路的艰辛,不过还好,在大家的支持下,总算是终见天日,谢谢那些给予我们无私帮助的朋友.您的支持,依然是我们无限的动力 ...
- iOS已发布应用中对异常信息捕获和处理
iOS已发布应用中对异常信息捕获和处理 iOS开发中我们会遇到程序抛出异常退出的情况,如果是在调试的过程中,异常的信息是一目了然,但是如果是在已经发布的程序中,获取异常的信息有时候是比较困难的. iO ...
- Eclipse4.3正式版已发布
Eclipse4.3正式版已发布,传送门http://www.eclipse.org/downloads/
随机推荐
- Ubuntu下配置Hyperledger Fabric环境
在win10系统的台式机上安装配置Hyperledger Fabric环境 安装Ubuntu 16.04 双系统 镜像下载地址:https://www.ubuntu.com/download/desk ...
- Mysql批量导入多个sql文件
DB_edusuntk文件夹下有2000多个个sql备份文件,如何批量导入?首先新建一个main.sql,然后在main.sql文件里面这么写: source C:/sql/1.sql; source ...
- js常用 方法 封装
// 监听滚动,用于列表页向下加载--------------------------------- function loadmore(callback) { $(window).scroll(fu ...
- mac下安装rabbitmq和php+rabbitq
一.首先使用brew安装rabbitmq brew install rabbitmq 安装完成,终端会出现如下内容,如图: 启动RabbitMQ 前台运行rabbitmq-server 后台运行bre ...
- Python每日一练(1)
这两天在做Python的每日一练,感觉收获颇丰,所以来记录分享一下,一共做了三个,涉及socket,PIL,pymysql三个库,另外终于开始了Flask框架的学习,后续也会做出一些分析 第一个是一个 ...
- Rocket - devices - bootrom
https://mp.weixin.qq.com/s/PylfNmJDRasTUj9fGp7gLQ 简单介绍bootrom目录中各个文件的实现. 1. Makefile 1) make过程 Makef ...
- jchdl - GSL实例 - Assign
https://mp.weixin.qq.com/s/MtHR3iolPd5VQq6AUE-JPg Assign是一个节点,把输入线直接赋值给输出线.在转换成Verilog时,这种类型的节点会直接 ...
- DevOps - 从渐进式交付说起(含实践 Demo)
作者:CODING - 王炜 1. 开篇 如果让你主导一款千万.甚至亿级用户产品的功能迭代,你会怎么做?你需要面对的挑战可能来自于: 商业战略的变化带来新的产品诉求,而产品的任何改动哪怕仅是界面调整, ...
- ActiveMQ 笔记(二)部署和DEMO(队列、主题)
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.部署操作 1. 部署在linux 上的acvtiveMQ 要可以通过前台windows 的页面访问, ...
- JavaScript (四) js的基本语法 - - 函数练习、arguments、函数定义、作用域、预解析
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.函数练习 1.求最值 // - 求2个数中的最大值 function getMax(num1, nu ...