.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( * );
}
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 = ;
stream.SetLength();
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[]);
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[], stream);
stream.Position = ;
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 = ;
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://ikende.com/Files/JsonSample.zip
.net core 在网络高并发下提高JSON的处理效率的更多相关文章
- Java生鲜电商平台-生鲜电商高并发下的接口幂等性实现与代码讲解
Java生鲜电商平台-生鲜电商高并发下的接口幂等性实现与代码讲解 说明:Java生鲜电商平台-生鲜电商高并发下的接口幂等性实现与代码讲解,实际系统中有很多操作,是不管做多少次,都应该产生一样的效果或返 ...
- 异构去堆叠 | 一种完美提升网络高可用SLA的方案
行业内接入网络去堆叠已经逐步成为主流方向,在大型互联网公司也已经批量部署.但由于京东集团不同的业务需求及历史原因,没有条件完全复制目前主流的ARP转主机路由方式的去堆叠方案,这促使我们设计一种尽可能满 ...
- 高并发下的Java数据结构(List、Set、Map、Queue)
由于并行程序与串行程序的不同特点,适用于串行程序的一些数据结构可能无法直接在并发环境下正常工作,这是因为这些数据结构不是线程安全的.本节将着重介绍一些可以用于多线程环境的数据结构,如并发List.并发 ...
- 分布式高并发下Actor模型
分布式高并发下Actor模型 写在开始 一般来说有两种策略用来在并发线程中进行通信:共享数据和消息传递.使用共享数据方式的并发编程面临的最大的一个问题就是数据条件竞争.处理各种锁的问题是让人十分头痛的 ...
- JDK1.7 高并发下的HashMap
HashMap的容量是有限的.当经过多次元素插入,使得HashMap达到一定饱和度时,Key映射位置发生冲突的几率会逐渐提高. 这时候,HashMap需要扩展它的长度,也就是进行Resize. 影响发 ...
- [Redis] - 高并发下Redis缓存穿透解决
高并发情况下,可能都要访问数据库,因为同时访问的方法,这时需要加入同步锁,当其中一个缓存获取后,其它的就要通过缓存获取数据. 方法一: 在方法上加上同步锁 synchronized //加同步锁,解决 ...
- 对HashMap的理解(二):高并发下的HashMap
在分析hashmap高并发场景之前,我们要先搞清楚ReHash这个概念.ReHash是HashMap在扩容时的一个步骤.HashMap的容量是有限的.当经过多次元素插入,使得HashMap达到一定饱和 ...
- springboot~高并发下耗时操作的实现
高并发下的耗时操作 高并发下,就是请求在一个时间点比较多时,很多写的请求打过来时,你的服务器承受很大的压力,当你的一个请求处理时间长时,这些请求将会把你的服务器线程耗尽,即你的主线程池里的线程将不会再 ...
- 用ASP.NET Core构建可检测的高可用服务--学习笔记
摘要 随着现代化微服务架构的发展,系统故障的定位与快速恢复面临着诸多挑战,构建可检测的服务,帮助线上保障团队时刻掌控应用的运行状况越来越重要.本次分享会讲解如何让 ASP .NET Core 应用与现 ...
随机推荐
- java(二、基础语法和基本数据类型)
Java 基础语法 一个Java程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作.下面简要介绍下类.对象.方法和实例变量的概念. 对象:对象是类的一个实例,有状态和行为.例如,一 ...
- c++右值引用以及使用
前几天看了一篇文章<4行代码看看右值引用> 觉得写得不错,但是觉得右值引用的内容还有很多可以去挖掘学习,所以总结了一下,希望能对右值引用有一个更加深层次的认识 一.几个基本概念 1.1左值 ...
- SSM-SpringMVC-16:SpringMVC中小论注解式开发之访问方式篇
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 访问方式可以指定,打个比方,你通过get方式进入登陆页面,通过post发送ajax数据库校验或者post提交 ...
- 【手记】解决启动SQL Server Management Studio 17时报Cannot find one of more components...的问题
刚装好SSMS 17.1准备体验,弹出: 一番搜索,普遍办法都是安装VS2015独立shell.删除某个注册表项什么的,没用,首先这个shell我是装了的,然后也没有那个注册表项.我自己尝试过重装sh ...
- python 零基础学习之路 02-python入门
不知不觉学习python已经两个月了,从一开始不知道如何对print的格式化,到现在可以手撸orm,这期间真的是 一个神奇的过程.为了巩固自己的基础知识,为后面的拓展埋下更好的伏笔,此文当以导师的博客 ...
- Web测试——翻页功能测试用例
参考:https://wenku.baidu.com/view/e6462707de80d4d8d15a4f1e.html?rec_flag=default&mark_pay_doc=2&am ...
- bootstrap学习地址2017.6.1
http://www.runoob.com/bootstrap/bootstrap-tutorial.html
- 陌陌架构分享 – Apple Push Notification Service
http://blog.latermoon.com/?p=878 先描述下基本概念,标准的iPhone应用是没有后台运行的,要实现实时推送消息到手机,需要借助Apple提供的APNS服务. iPhon ...
- 关于CSS定位属性 position 的使用
CSS中一般通过浮动和定位来对标签进行位置操作.下面我们来讨论一下定位的用法和需要注意的地方. 1.首先,说一下position的几个属性值 (1)none属性值,这个是定义不进行定位,默认为不定位, ...
- bzoj 3505 [Cqoi2014]数三角形 组合
ans=所有的三点排列-共行的-共列的-斜着一条线的 斜着的枚举每个点和原点的gcd,反过来也可以,还能左右,上下挪 #include<cstdio> #include<cstrin ...