.net core如何在网络高并发下提高JSON的处理效率详解
 更新时间:2019年04月12日 09:42:29   作者:smark  

这篇文章主要给大家介绍了关于.net core如何在网络高并发下提高JSON的处理效率的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用.net core具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言
现有的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测试上已经引入。可以尝试一下使用,组件开源地址: 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:[email protected]
Github: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序列化处理。
下载测试代码:xiazai.jb51.net/201904/yuanma/JsonSample(jb51).rar

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

您可能感兴趣的文章:asp.net core 系列之并发冲突的深入理解.net core并发下线程安全问题详解.net core并发请求发送HttpWebRequest的坑解决.NET Core 中的并发编程

core
高并发
json

相关文章
Grid或者DataTable中数据导出为Excel原来这么简单以前一直认为,将Grid 或者DataTable中的数据导出到Excel功能实现会非常复杂,可能会想用什么类库什么的或者实在太难就用csv算了,没想到真的很简单,需要了解的朋友可以参考下 2012-12-12
.NET 线程基础的使用介绍本篇文章介绍了,.NET 线程基础的使用说明,需要的朋友参考下 2013-05-05
asp.net Cookie跨域、虚拟目录等设置方法Cookie跨域、虚拟目录等设置方法,需要的朋友可以参考下。 2009-11-11
ASP.NET中上传并读取Excel文件数据示例如何打开Excel数据库文件,想必有很多朋友都不清楚吧,下面通过一个简单的例子,实现读取Excel数据文件 2014-05-05
asp.net实现将Excel中多个sheet数据导入到SQLSERVER中的方法这篇文章主要介绍了asp.net实现将Excel中多个sheet数据导入到SQLSERVER中的方法,涉及asp.net针对Excel的读取与数据库操作相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下 2015-12-12
微信小程序 (十七)input 组件详细介绍这篇文章主要介绍了微信小程序 input 组件详细介绍的相关资料,需要的朋友可以参考下 2016-09-09
ASP.NET Core静态文件的使用方法这篇文章主要给大家介绍了关于ASP.NET Core静态文件的使用方法,文中通过示例代码介绍的非常详细,对大家学习或者使用ASP.NET Core具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧 2019-05-05
asp.net中List的使用方法.net真是方便,这几天帮朋友写了个小软件,用它还真感觉轻松自在,很称手,自带的类库既丰富又实用 2008-10-10
asp.net窗体的打开和关闭(输出js)asp.net窗体的打开和关闭(输出js),需要的朋友可以参考下。 2011-06-06
ASP.NET验证码实现(附源码)这篇文章主要介绍了ASP.NET验证码实现过程,并为大家分享了源码下载,感兴趣的小伙伴们可以参考一下 2015-11-11

最新评论

声明:本站(华域联盟www.cnhackhy.com)所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。