Json序列化与反序列化导致多线程运行速度和单线程运行速度一致问题

本文探讨了在处理大量JSON文件时,使用多线程而非单线程的原因。文章指出,传统的JsonConvert.DeserializeObject方法在多线程环境中并未显著提升效率。为解决这一问题,作者推荐了微软提供的高性能JSON库System.Text.Json。通过JsonDocument.Parse方法,可以实现JSON的高效序列化和反序列化。尽管该库的使用较为复杂,但对于追求极致性能的场景,它是理想选择。通过示例代码,文章展示了如何使用JsonDocument及其属性来获取JSON数据,并解释了为何TryGetProperty方法有利于处理不存在的属性。文章最后提到,使用System.Text.Json库在多线程环境中能显著提升处理速度,性能提升可达三分之二。
摘要由CSDN通过智能技术生成

紧跟上篇文章 十个进程开启十个bash后一致写入命令执行完毕之后产生了很多很多的文件,博主需要对这些文件同意处理,也就是说对几十万个文件进行处理,想了又想,单线程处理那么多数据肯定不行,于是乎想到了使用多线程,紧接着就引发了一系列问题,其中做大的问题就是json序列化,导致了多条线程运行和单线程运行时间一致问题。

我们正常去读取json文件转成一般是通过实体类去使用JsonConvert.DeserializeObject方法进行接收的,然后再通过实体类去进行一系列的操作,目前遇到的问题就是读取上万的json文件进行反序列化与序列化进行操作,如果一条一条的去操作的话速度可谓是非常非常慢,然后经过大佬的推荐和自己了解决定使用微软专门推出的一个操作json的类。

这个类说的也非常清楚,提供高性能、低分配和标准兼容的功能,以处理 JavaScript 对象表示法 (JSON),其中包括将对象序列化为 JSON 文本以及将 JSON 文本反序列化为对象(内置 UTF-8 支持)。 它还提供类型以用于读取和写入编码为 UTF-8 的 JSON 文本,以及用于创建内存中文档对象模型 (DOM) 以在数据的结构化视图中随机访问 JSON 元素。

虽然这个类库专门针对于性能来优化的,但是使用起来往往非常的困难,没有我们大众所使用的JsonConvert.DeserializeObject方便,但是如像我一样对待性能有极致的要求的话,可以使用这个类库,用法也非常简单,下面我给出例子

引入命名空间:

System.Text.Json

那么具体如何使用呢?我这里给出具体的使用方法以及详细的例子。

JsonDocument document1 = null;

StreamReader f2 = new StreamReader(filePath, Encoding.UTF8);
String line;
while ((line = f2.ReadLine()) != null)
{
    document1 = JsonDocument.Parse(line);
}
f2.Close();
f2.Dispose();                

这里我们去读取filepath,filepath是json文件路径。我们使用  JsonDocument.Parse对json文件进行操作。这个方法表示单个 JSON 字节值的 UTF-8 编码文本形式的序列分析为 JsonDocument。

把json文件序列分析为JsonDocument类型了下面就是对这个类型进行操作,为什么现在好多人不喜欢使用这种方法,大概率是因为取值比较难

对于JsonDocument如何取出我们想要的值或者节点呢?看下面的例子:

{
  "ClassName": "Science",
  "Teacher\u0027s Name": "Jane",
  "Semester": "2019-01-01",
  "Students": [
    {
      "Name": "John",
      "Grade": 94.3
    },
    {
      "Name": "James",
      "Grade": 81.0
    },
    {
      "Name": "Julia",
      "Grade": 91.9
    },
    {
      "Name": "Jessica",
      "Grade": 72.4
    },
    {
      "Name": "Johnathan"
    }
  ],
  "Final": true
}

上述是一个json文件内的数据,我们解析JsonDocument如何解析出Class Name节点值呢?

可以使用如下操作

//定义变量去接收
var className = "0";
//判断我们解析出来的JsonDocument是否为空
if (document1 != null)
{
    JsonElement root = document1.RootElement;
    className = root.TryGetProperty("ClassName", out var temp) ? temp.GetInt32().ToString() : "0";
}

首先使用 JsonDocument.RootElement属性 获取此 JSON 文档的根元素。

对于根元素进行解析,JsonElemet.TryGetProperty() 查找当前对象中名为 ClassName 的属性,返回一个指示此类属性是否存在的值。 如果此属性存在,会将其值分配给 value 参数。现在value参数对应temp,解析时还应注意属性值类型,如果为string类型则使用GetString(),去进行转换,int类型可以使用GetInt32(),进行转换,具体其他类型可以查看微软官方给出的类型。

使用TryGetProperty()方法有什么好处呢?

可以去判断json文件内有没有当前的属性,如果有的话,去返回属性值,无,则返回null。

现在我们取单独属性已经会了,那么如何取数组呢?如何取数组对象呢?

例子:

double sum = 0;
int count = 0;

using (JsonDocument document = JsonDocument.Parse(jsonString))
{
    JsonElement root = document.RootElement;
    JsonElement studentsElement = root.GetProperty("Students");
    count = studentsElement.GetArrayLength();

    foreach (JsonElement student in studentsElement.EnumerateArray())
    {
        if (student.TryGetProperty("Grade", out JsonElement gradeElement))
        {
            sum += gradeElement.GetDouble();
        }
        else
        {
            sum += 70;
        }
    }
}

double average = sum / count;
Console.WriteLine($"Average grade : {average}");

上面这个例子是微软官方给出的例子,但是使用与我们已经知道json文件格式的情况。

使用之前我们可以使用TryGetProperty方法先判断json属性是否存在,存在的话去定义一个value值进行接收,先判断是否为存在,存在则把value值进行遍历,然后再去判断这个数组内的属性是否存在,存在的话返回属性值,以此类推便可以拿到所有的json文件中的属性值啦!

https://zhuanlan.zhihu.com/p/506079956
https://zhuanlan.zhihu.com/p/506098842
https://blog.csdn.net/weixin_39929847/article/details/124455334
https://blog.csdn.net/weixin_39929847/article/details/124454691
https://blog.csdn.net/weixin_39929847/article/details/124454309
https://blog.csdn.net/weixin_39929847/article/details/124453899
https://blog.csdn.net/weixin_39929847/article/details/124453668
https://tieba.baidu.com/p/7813260619
https://tieba.baidu.com/p/7812163552
https://www.bilibili.com/read/cv16345495
https://www.bilibili.com/read/cv16345519
https://www.bilibili.com/read/cv16345525
https://www.bilibili.com/read/cv16345545
https://page.om.qq.com/page/OWFnlXdkJYMhF7Xhdcg2PGJQ0
http://www.163.com/dy/article/H623FFVF05535RIY.html
https://www.sohu.com/a/542082544_121383096
https://www.163.com/dy/article/H624OC8U05535RIY.html
https://page.om.qq.com/page/OhIdJ-NCz2T4T3UqqVI9oxkA0
https://page.om.qq.com/page/O99J82LTKCoFAETVu6H285TQ0
http://www.163.com/dy/article/H626N9QU05535RIY.html
https://www.sohu.com/a/542093797_121383096
https://www.douban.com/note/830407034/
https://tieba.baidu.com/p/7814190424
https://www.163.com/dy/article/H64MFM7105535RIY.html
https://www.163.com/dy/article/H64N29JV05535RIY.html
https://www.sohu.com/a/542409382_121383096
https://www.sohu.com/a/542406560_121383096
https://www.sohu.com/a/542422621_121383096
https://www.sohu.com/a/542420251_121383096
https://page.om.qq.com/page/OD9pw1SY2654yqAFZle7vjRQ0
https://page.om.qq.com/page/OS4lfl82KNkfF7wJ8DnGPj_A0
https://page.om.qq.com/page/OG2FAQSe2vtV9dklEp9R_8xA0
https://page.om.qq.com/page/Onewu1MxyUfFIf3LGCXJlLyw0
https://page.om.qq.com/page/OeEdTnEekPFsHxVfjRHhzzvg0
https://www.douban.com/note/830410438/
https://tieba.baidu.com/p/7815601548
https://www.bilibili.com/read/cv16378212
https://www.bilibili.com/read/cv16377981
https://www.bilibili.com/read/cv16377871
https://www.bilibili.com/read/cv16375769
https://www.bilibili.com/read/cv16375619
https://zhuanlan.zhihu.com/p/507401368
https://page.om.qq.com/page/OQg_0AyHy8MVXSiIeexnkFKg0
https://page.om.qq.com/page/O8OrwDvj2BxN_loRHbEnpX9g0
https://page.om.qq.com/page/O2-kQx8P_6Lhan19uYuFBQSA0

性能提升:说了这么多到底这种方法能够提升多少速度呢,经过博主测试JsonConvert.DeserializeObject方法在线程或者进程内使用的话开启多个和单个线程(进程)速度相差基本不大,就好比我开了十个线程,去读取十万个文件,结果和单个线程去读取十万个文件相差几秒??是不是非常离谱。

换用这种高性能处理json文件的类库之后,开启十个线程去操作文件速度直接减少了三分之二!!!!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值