数码控科技猎奇Iphone动漫星座游戏电竞lolcosplay王者荣耀攻略allcnewsBLOGNEWSBLOGASKBLOGBLOGZSK全部技术问答问答技术问答it问答代码软件新闻开发博客电脑/网络手机/数码笔记本电脑互联网操作系统软件硬件编程开发360产品资源分享电脑知识文档中心IT全部全部分类全部分类技术牛文全部分类教程最新网页制作cms教程平面设计媒体动画操作系统网站运营网络安全服务器教程数据库工具网络安全软件教学vbscript正则表达式javascript批处理更多»编程更新教程更新游戏更新allitnewsJava新闻网络医疗信息化安全创业站长电商科技访谈域名会议专栏创业动态融资创投创业学院 / 产品经理创业公司人物访谈营销开发数据库服务器系统虚拟化云计算嵌入式移动开发作业作业1常见软件all电脑网络手机数码生活游戏体育运动明星影音休闲爱好文化艺术社会民生教育科学医疗健康金融管理情感社交地区其他电脑互联网软件硬件编程开发360相关产品手机平板其他电子产品摄影器材360硬件通讯智能设备购物时尚生活常识美容塑身服装服饰出行旅游交通汽车购房置业家居装修美食烹饪单机电脑游戏网页游戏电视游戏桌游棋牌游戏手机游戏小游戏掌机游戏客户端游戏集体游戏其他游戏体育赛事篮球足球其他运动球类运动赛车健身运动运动用品影视娱乐人物音乐动漫摄影摄像收藏宠物幽默搞笑起名花鸟鱼虫茶艺彩票星座占卜书画美术舞蹈小说图书器乐声乐小品相声戏剧戏曲手工艺品历史话题时事政治就业职场军事国防节日风俗法律法规宗教礼仪礼节自然灾害360维权社会人物升学入学人文社科外语资格考试公务员留学出国家庭教育学习方法语文物理生物工程学农业数学化学健康知识心理健康孕育早教内科外科妇产科儿科皮肤科五官科男科整形中医药品传染科其他疾病医院两性肿瘤科创业投资企业管理财务税务银行股票金融理财基金债券保险贸易商务文书国民经济爱情婚姻家庭烦恼北京上海重庆天津黑龙江吉林辽宁河北内蒙古山西陕西宁夏甘肃青海新疆西藏四川贵州云南河南湖北湖南山东江苏浙江安徽江西福建广东广西海南香港澳门台湾海外地区

.net core如何在网络高并发下提高JSON的处理效率详解

来源:脚本之家  责任编辑:小易  

前言

现有的webapi一般都基于JSON的格式来处理数据,由于JSON是一个文本类的序列化协议所以在性能上自然就相对低效一些。在.net中常用Newtonsoft.Json是最常用的组件,由于提供简便基于完整的json的String方法使用起来非常方便;但也正是这原因导致Newtonsoft.Json在性能上一直被说慢,虽然Newtonsoft.Json提供Stream的方式来处理JSON不过想复用writer和reader还是需要一些应用技巧。如果需要在网络通讯中应用JSON,那在这里介绍一下SpanJson这个组件,并通过一些测试来讲述如何使用它。

SpanJson介绍

SpanJson是一个性能相对不错的JSON组件,组件直接提供了byte[]和stream两种操作方式,而这两种方式非常适合在构建自有网络通讯上使用。通过这些基础的字节和流结构来处理可以相对降低一个大string的开销。不过这个组件的热度并不高,完善成度暂还不如Newtonsoft.Json,不过asp.net core 在FrameworkBenchmarks测试上已经引入。可以尝试一下使用,组件开源地址: https://github.com/Tornhoof/SpanJson (本地下载)

性能测试

组件提供的方法相对比较少,从设计上来说更多是针对通讯方面的支持。基于Stream的序列化可以直接挂载在NetStream上,这样可以节省数据复制带来的开销。不过反序列化不能直接在有混合数据的Stream上进行,这或多或少有些可惜。从issues的解答来看作者也不太愿意在混合数据流上进行调整。接下来针对bytes和Stream使用进行一个性能测试,而Stream则采用一个可复用池的设计

MemoryStream 池的设计

public class MemoryStreamPool
 {

  private static System.Collections.Concurrent.ConcurrentStack<JsonMemoryStream> mPool = new System.Collections.Concurrent.ConcurrentStack<JsonMemoryStream>();

  public static Stream Pop()
  {
   if (!mPool.TryPop(out JsonMemoryStream result))
   {
    result = new JsonMemoryStream(1024 * 32);
   }
   return result;
  }


  public class JsonMemoryStream : MemoryStream
  {
   public JsonMemoryStream(int size) : base(size) { }

   protected override void Dispose(bool disposing)
   {
    MemoryStreamPool.Push(this);
   }

  }

  private static void Push(JsonMemoryStream stream)
  {
   stream.Position = 0;
   stream.SetLength(0);
   mPool.Push(stream);
  }
 }

测试内容

测试的方式主要针对一个简单的对象和一个对象列表,然后在不同线程下bytes和Stream pool这两种方式的性能差别;压测的线程数据分别是1,2,4,8,16,24,32,每次测试执行的总数是100万次,然后统计出执行需要的时间和并发量。 测试代码:

public class Bytes_JSON : BeetleX.Benchmark.BenchmarkBase
 {
  protected override void OnTest()
  {
   while (Increment())
   {
    var data = SpanJson.JsonSerializer.NonGeneric.Utf8.Serialize(DataHelper.Defalut.Employees[0]);
    var employees = SpanJson.JsonSerializer.Generic.Utf8.Deserialize<Employee>(data);
   }
  }
 }

 public class StreamPool_JSON : BeetleX.Benchmark.BenchmarkBase
 {
  protected override void OnTest()
  {
   RunTest();
  }

  private async void RunTest()
  {
   while (Increment())
   {
    using (Stream stream = MemoryStreamPool.Pop())
    {
     await SpanJson.JsonSerializer.NonGeneric.Utf8.SerializeAsync(DataHelper.Defalut.Employees[0], stream);
     stream.Position = 0;
     var employees = await SpanJson.JsonSerializer.Generic.Utf8.DeserializeAsync<Employee>(stream);
    }
   }
  }
 }


 public class Bytes_JSON_List : BeetleX.Benchmark.BenchmarkBase
 {
  protected override void OnTest()
  {
   while (Increment())
   {
    var data = SpanJson.JsonSerializer.NonGeneric.Utf8.Serialize(DataHelper.Defalut.Employees);
    var employees = SpanJson.JsonSerializer.Generic.Utf8.Deserialize<List<Employee>>(data);
   }
  }
 }

 public class StreamPool_JSON_List : BeetleX.Benchmark.BenchmarkBase
 {
  protected override void OnTest()
  {
   RunTest();
  }

  private async void RunTest()
  {
   while (Increment())
   {
    using (Stream stream = MemoryStreamPool.Pop())
    {
     await SpanJson.JsonSerializer.NonGeneric.Utf8.SerializeAsync(DataHelper.Defalut.Employees, stream);
     stream.Position = 0;
     var employees = await SpanJson.JsonSerializer.Generic.Utf8.DeserializeAsync<List<Employee>>(stream);
    }
   }
  }
 }

测试结果

C:\Users\Administrator\Desktop\json_test>dotnet JsonSample.dll
BeetleX.Benchmark [0.5.4.0] Copyright ? ikende.com 2019
EMail:henryfan@msn.com
Github:https://github.com/ikende
-------------------------------------------------------------------------------
|Name                          | Round| Threads|     Count| Use time(s)|   Sec|
-------------------------------------------------------------------------------
|Bytes_JSON                    |     1|       1|   1000000|        5.57|179580|
-------------------------------------------------------------------------------
|StreamPool_JSON               |     1|       1|   1000000|        5.44|183898|
-------------------------------------------------------------------------------
|Bytes_JSON_List               |     1|       1|   1000000|       43.01| 23248|
-------------------------------------------------------------------------------
|StreamPool_JSON_List          |     1|       1|   1000000|       42.75| 23391|
-------------------------------------------------------------------------------
|Bytes_JSON                    |     1|       2|   1000000|        2.81|355990|
-------------------------------------------------------------------------------
|StreamPool_JSON               |     1|       2|   1000000|        2.95|338969|
-------------------------------------------------------------------------------
|Bytes_JSON_List               |     1|       2|   1000000|       23.16| 43180|
-------------------------------------------------------------------------------
|StreamPool_JSON_List          |     1|       2|   1000000|        22.4| 44650|
-------------------------------------------------------------------------------
|Bytes_JSON                    |     1|       4|   1000000|        1.51|661246|
-------------------------------------------------------------------------------
|StreamPool_JSON               |     1|       4|   1000000|        1.57|636130|
-------------------------------------------------------------------------------
|Bytes_JSON_List               |     1|       4|   1000000|       13.35| 74915|
-------------------------------------------------------------------------------
|StreamPool_JSON_List          |     1|       4|   1000000|       11.97| 83508|
-------------------------------------------------------------------------------
|Bytes_JSON                    |     1|       8|   1000000|         .83|1199453|
--------------------------------------------------------------------------------
|StreamPool_JSON               |     1|       8|   1000000|         .88|1142495|
--------------------------------------------------------------------------------
|Bytes_JSON_List               |     1|       8|   1000000|        9.24|108228|
-------------------------------------------------------------------------------
|StreamPool_JSON_List          |     1|       8|   1000000|        6.75|148132|
-------------------------------------------------------------------------------
|Bytes_JSON                    |     1|      16|   1000000|         .56|1795910|
--------------------------------------------------------------------------------
|StreamPool_JSON               |     1|      16|   1000000|         .74|1344851|
--------------------------------------------------------------------------------
|Bytes_JSON_List               |     1|      16|   1000000|        7.67|130424|
-------------------------------------------------------------------------------
|StreamPool_JSON_List          |     1|      16|   1000000|        4.61|216860|
-------------------------------------------------------------------------------
|Bytes_JSON                    |     1|      24|   1000000|         .54|1849769|
--------------------------------------------------------------------------------
|StreamPool_JSON               |     1|      24|   1000000|         .73|1361382|
--------------------------------------------------------------------------------
|Bytes_JSON_List               |     1|      24|   1000000|        7.61|131373|
-------------------------------------------------------------------------------
|StreamPool_JSON_List          |     1|      24|   1000000|         4.7|212779|
-------------------------------------------------------------------------------
|Bytes_JSON                    |     1|      32|   1000000|         .55|1825484|
--------------------------------------------------------------------------------
|StreamPool_JSON               |     1|      32|   1000000|         .75|1339050|
--------------------------------------------------------------------------------
|Bytes_JSON_List               |     1|      32|   1000000|        8.01|124885|
-------------------------------------------------------------------------------
|StreamPool_JSON_List          |     1|      32|   1000000|        5.21|192038|
-------------------------------------------------------------------------------
Test completed!

总结

从测试结果来看,如果序列化的对象比小,那可以直接基于bytes的方式。虽然会产生新的bytes对象,不过由于对象比较小,引起的分配和回收并没有对象池操作上的损耗高。不过如果对象相对复杂些的情况下,那对象池的作用就能发挥出来,并发越大其作用越明显!,当并发线程数达到8的时候,效率已经明显抛开!由于业务上的数据信息都相对比较复杂些,所以在处理上还是建议通过对象池的方式来完成json序列化处理。

下载测试代码:http://xiazai.jb51.net/201904/yuanma/JsonSample(jb51).rar

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

您可能感兴趣的文章:


  • 本文相关:
  • .netcore获取json和xml格式的配置信息
  • asp.net core web中使用appsettings.json配置文件的方法
  • .net core简单读取json配置文件
  • 详解asp.net core 在 json 文件中配置依赖注入
  • asp.net core project.json文件(5)
  • asp.netcore1.1版本去掉project.json后如何打包生成跨平台包
  • asp.net core 获取 macaddress 地址方法示例
  • viewstate和datatable动态录入数据示例
  • 在c#中生成与php一样的md5 hash code的方法
  • 解决uploadify使用时session发生丢失问题的方法
  • c# 文件保存到数据库中或者从数据库中读取文件
  • asp.net core项目结构教程(4)
  • .net之后台用户权限管理实现
  • clickonce diy全自动更新下载升级的自我实现
  • asp.net实现利用反射,泛型,静态方法快速获取表单值到model的方
  • asp.net操作ini文件示例
  • 免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved