.net core 在网络高并发下提高JSON的处理效率
2019-04-11 13:18
441 查看
现有的
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![/code]
总结
从测试结果来看,如果序列化的对象比小,那可以直接基于bytes的方式。虽然会产生新的bytes对象,不过由于对象比较小,引起的分配和回收并没有对象池操作上的损耗高。不过如果对象相对复杂些的情况下,那对象池的作用就能发挥出来,并发越大其作用越明显!,当并发线程数达到8的时候,效率已经明显抛开!由于业务上的数据信息都相对比较复杂些,所以在处理上还是建议通过对象池的方式来完成json序列化处理。
下载测试代码
相关文章推荐
- Linux(Centos )的网络内核参数优化来提高服务器并发处理能力
- 用消息发送队列提高网络应用处理效率
- Linux(Centos )的网络内核参数优化来提高服务器并发处理能力
- Linux 网络内核参数优化来提高服务器并发处理能力
- Linux(Centos )的网络内核参数优化来提高服务器并发处理能力【转】
- Linux(Centos )的网络内核参数优化来提高服务器并发处理能力
- Linux(Centos )的网络内核参数优化来提高服务器并发处理能力
- Centos网络内核参数优化来提高服务器并发处理能力
- 高并发高性能下提高SERVER性能的一种网络处理模式
- 高并发、海量数据处理尽量少使用using也能提升效率
- 如何提高Web服务端并发效率的异步编程技术
- OpenERP 7.0成倍提高并发处理能力
- iOS面试题--网络--如何处理多个网络请求的并发的情况
- 采用jdbc批处理 提高jdbc效率
- 优化Linux的内核参数来提高服务器并发处理能力
- 优化Linux的内核参数来提高服务器并发处理能力
- Thread-使用同步块来有效的减少同步范围,可以提高代码并发运行的效率。
- 在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
- 设置cocos2d 的音效回放参数,提高处理效率
- 网络环境下提高图书编目工作效率搞高的方法