微软终于追上了?

图片来自 Glenn Carstens-Peters Unsplash

欢迎来到.NET性能系列的另一章。这个系列的特点是对.NET世界中许多不同的主题进行研究、基准和比较。正如标题所说的那样,重点在于使用最新的.NET7的性能。你将看到哪种方法是实现特定主题的最快方法,以及大量的技巧和窍门,你如何能以较低的努力最大化你的代码性能。如果你对这些主题感兴趣,请继续关注

在这篇文章中,我们将比较两个最突出的.NET的json框架。:

Newtonsofts Json.NETMicrosofts System.Text.Json.

Newtonsoft.Json是NuGet上下载量最大的软件包,下载量超过23亿System.Text.Json稍稍落后,大约有6亿次下载。然而,我们需要考虑的是,System.Text.Json自.NET Core 3.1起就默认随.NET SDK交付。既然如此,Newtonsoft似乎仍然是最受欢迎的json框架。让我们来看看,它是否能保持它的名次,或者微软是否在性能方面缓慢但肯定地领先。

测试方案

为了模拟现实生活中应用的真实场景,我们将测试两个主要用例。

  • 第一,单个大数据集的序列化和反序列化。
  • 第二是许多小数据集的序列化和反序列化。

一个真实的场景也需要真实的数据。对于测试数据集,我决定使用NuGet包Bogus。通过Bogus,我能够快速生成许多不同的用户,包括个人姓名、电子邮件、ID等。

[Params(10000)]
public int Count { get; set; } private List<User> testUsers; [GlobalSetup]
public void GlobalSetup()
{
var faker = new Faker<User>()
.CustomInstantiator(f => new User(
Guid.NewGuid(),
f.Name.FirstName(),
f.Name.LastName(),
f.Name.FullName(),
f.Internet.UserName(f.Name.FirstName(), f.Name.LastName()),
f.Internet.Email(f.Name.FirstName(), f.Name.LastName())
)); testUsers = faker.Generate(Count);
}

对于基准,我们将使用每个软件包的最新版本,目前是(2022年10月):

  • Newtonsoft.Json — 13.0.1 and
  • System.Text.Json — 7.0.0-rc.2

序列化测试

序列化大对象

为了测试一个大对象的序列化,我们简单地使用List<User>,我们在GlobalSetup()方法中设置了它。我们的基准方法看起来像这样:

[Benchmark(Baseline = true)]
public void NewtonsoftSerializeBigData() =>
_ = Newtonsoft.Json.JsonConvert.SerializeObject(testUsers); [Benchmark]
public void MicrosoftSerializeBigData() =>
_ = System.Text.Json.JsonSerializer.Serialize(testUsers);

这些方法都使用默认的ContractResolver,它只被实例化一次,因此是两个框架中性能最好的序列化选项。如果你使用自定义的JsonSerializerSettings,注意不要多次实例化ContractResolver,否则你会降低很多性能。

现在我们来看看结果:

Method Count Mean Ratio Allocated Alloc Ratio
NewtonsoftSerializeBigData 10000 7.609 ms 1.00 8.09 MB 1.00
MicrosoftSerializeBigData 10000 3.712 ms 0.49 3.42 MB 0.42

尽管Newtonsoft在他们的第一个文档网站上说。

高性能:比.NET的内置JSON序列化器快

我们可以清楚地看到,到目前为止,他们并不比内置的JSON序列化器快。至少在这个用例中是这样。让我们来看看,在其他使用情况下是否也是如此。

序列化许多小对象

这个用例在实际应用中比较常见,例如在REST-Apis中,每个网络请求都必须处理JSON序列化数据,并且也要用JSON序列化数据进行响应。

为了实现这个用例,我们使用之前建立的List<User>,并简单地循环通过它,同时单独序列化每个用户。

[Benchmark(Baseline = true)]
public void NewtonsoftSerializeMuchData()
{
foreach (var user in testUsers)
{
_ = Newtonsoft.Json.JsonConvert.SerializeObject(user);
}
} [Benchmark]
public void MicrosoftSerializeMuchData()
{
foreach (var user in testUsers)
{
_ = System.Text.Json.JsonSerializer.Serialize(user);
}
}

在我的机器上,这个基准测试导致了以下结果:

Method Count Mean Ratio Allocated Alloc Ratio
NewtonsoftSerializeMuchData 10000 8.087 ms 1.00 17.14 MB 1.00
MicrosoftSerializeMuchData 10000 3.944 ms 0.49 3.64 MB 0.21

我们可以看到对于许多小对象来说,性能又快了近100%。不仅System.Text.Json的性能比Newtonsoft快了一倍,而且堆分配的内存甚至少了5倍! 正如我在以前的文章中提到的,节省堆内存甚至比速度更重要,你在这里看到了。堆内存最终将不得不被垃圾回收,这将阻塞你的整个应用程序的执行。

反序列化测试

在现实世界的应用中,你不仅要序列化,还要从JSON序列化的字符串中反序列化对象。在下面的基准中,我们将再次使用Bogus,创建一组用户,但这次我们要把它们序列化为一个大的字符串,用于大数据对象,并把许多小数据对象序列化为List<string>

private string serializedTestUsers;

private List<string> serializedTestUsersList = new();

[GlobalSetup]
public void GlobalSetup()
{
var faker = new Faker<User>()
.CustomInstantiator(f => new User(
Guid.NewGuid(),
f.Name.FirstName(),
f.Name.LastName(),
f.Name.FullName(),
f.Internet.UserName(f.Name.FirstName(), f.Name.LastName()),
f.Internet.Email(f.Name.FirstName(), f.Name.LastName())
)); var testUsers = faker.Generate(Count); serializedTestUsers = JsonSerializer.Serialize(testUsers); foreach (var user in testUsers.Select(u => JsonSerializer.Serialize(u)))
{
serializedTestUsersList.Add(user);
}
}

反序列化大对象

第一个反序列化基准将一个大的JSON字符串反序列化为相应的.NET对象。在这种情况下,它又是List<User>,我们在前面的例子中也使用了它。

[Benchmark(Baseline = true)]
public void NewtonsoftDeserializeBigData() =>
_ = Newtonsoft.Json.JsonConvert.DeserializeObject<List<User>>(serializedTestUsers); [Benchmark]
public void MicrosoftDeserializeBigData() =>
_ = System.Text.Json.JsonSerializer.Deserialize<List<User>>(serializedTestUsers);

在我的机器上运行这些基准测试,得出以下结果:

Method Count Mean Ratio Allocated Alloc Ratio
NewtonsoftDeserializeBigData 10000 21.20 ms 1.00 10.55 MB 1.00
MicrosoftDeserializeBigData 10000 12.12 ms 0.57 6.17 MB 0.59

就性能而言,微软仍然远远领先于Newtonsoft。然而,我们可以看到,Newtonsoft并没有慢一半,而是慢了40%左右,这在与序列化基准的直接比较中是一个进步。

反序列化许多小对象

本章的最后一个基准是许多小对象的反序列化。在这里,我们使用我们在上面的GlobalSetup()方法中初始化的List<string>,在一个循环中反序列化数据对象:

[Benchmark(Baseline = true)]
public void NewtonsoftDeserializeMuchData()
{
foreach (var user in serializedTestUsersList)
{
_ = Newtonsoft.Json.JsonConvert.DeserializeObject<User>(user);
}
} [Benchmark]
public void MicrosoftDeserializeMuchData()
{
foreach (var user in serializedTestUsersList)
{
_ = System.Text.Json.JsonSerializer.Deserialize<User>(user);
}
}

其结果甚至比相关的序列化基准更令人吃惊:

Method Count Mean Ratio Allocated Alloc Ratio
NewtonsoftDeserializeMuchData 10000 15.577 ms 1.00 35.54 MB 1.00
MicrosoftDeserializeMuchData 10000 7.916 ms 0.51 4.8 MB 0.14

在Microsofts框架下,速度又快了一倍,内存效率是惊人的7倍,比Newtonsoft还要好!

总结

尽管Newtonsoft在他们的文档上说:

高性能:比.NET的内置JSON序列化器更快

很明显,至少从.NET 7开始,Microsofts的System.Text.Json在所有测试的用例中至少快了一倍,命名为。

  • 序列化一个大数据集
  • 序列化许多小数据集
  • 对一个大数据集进行反序列化
  • 对许多小数据集进行反序列化

所有这些都是在每个框架的默认序列化器设置下进行的。

不仅速度快了100%,而且在某些情况下,分配的内存甚至比Newtonsoft的效率高5倍以上。

我甚至认为,可以推断出结果,目前使用System.Text.JsonNewtonsoft.Json更快。

请记住,这些结果只对最新的.NET 7有效。如果你使用的是其他版本的.NET,情况可能正好相反,Newtonsoft可能会更快。

我希望,我的文章可以帮助你对序列化器做出选择选择,并让你对性能和基准测试的世界有一个有趣的切入点。

如果你喜欢这个系列的文章,请一定要关注我,因为还有很多有趣的话题等着你。

谢谢你的阅读!

版权

原文版权:Tobias Streng

翻译版权:InCerry

原文链接:https://medium.com/@tobias.streng/net-performance-series-2-newtonsoft-vs-system-text-json-2bf43e037db0

.NET性能系列文章二:Newtonsoft.Json vs. System.Text.Json的更多相关文章

  1. In .net 4.8,calculate the time cost of serialization in BinaryFormatter,NewtonSoft.json,and System.Text.Json.JsonSerializer.Serialize

    using ConsoleApp390.Model; using Newtonsoft.Json; using System; using System.Collections.Generic; us ...

  2. .NET性能系列文章一:.NET7的性能改进

    这些方法在.NET7中变得更快 照片来自 CHUTTERSNAP 的 Unsplash 欢迎阅读.NET性能系列的第一章.这一系列的特点是对.NET世界中许多不同的主题进行研究.比较性能.正如标题所说 ...

  3. [译]试用新的System.Text.Json API

    译注 可能有的小伙伴已经知道了,在.NET Core 3.0中微软加入了对JSON的内置支持. 一直以来.NET开发者们已经习惯使用Json.NET这个强大的库来处理JSON. 那么.NET为什么要增 ...

  4. 【译】System.Text.Json 的下一步是什么

    .NET 5.0 最近发布了,并带来了许多新特性和性能改进.System.Text.Json 也不例外.我们改进了性能和可靠性,并使熟悉 Newtonsoft.Json 的人更容易采用它.在这篇文章中 ...

  5. 在.Net Core 3.0中尝试新的System.Text.Json API

    .NET Core 3.0提供了一个名为System.Text.Json的全新命名空间,它支持reader/writer,文档对象模型(DOM)和序列化程序.在此博客文章中,我将介绍它如何工作以及如何 ...

  6. .net core中关于System.Text.Json的使用

    在.Net Framework的时候序列化经常使用Newtonsoft.Json插件来使用,而在.Net Core中自带了System.Text.Json,号称性能更好,今天抽空就来捣鼓一下. 使用起 ...

  7. c# System.Text.Json 精讲

    本文内容来自我写的开源电子书<WoW C#>,现在正在编写中,可以去WOW-Csharp/学习路径总结.md at master · sogeisetsu/WOW-Csharp (gith ...

  8. System.Text.Json 自定义Converter实现时间转换

    Newtonsoft.Json与System.Text.Json区别 在 Newtonsoft.Json中可以使用例如 .AddJsonOptions(options => { options. ...

  9. .NET Core 3.0 System.Text.Json 和 Newtonsoft.Json 行为不一致问题及解决办法

    行为不一致 .NET Core 3.0 新出了个内置的 JSON 库, 全名叫做尼古拉斯 System.Text.Json - 性能更高占用内存更少这都不是事... 对我来说, 很多或大或小的项目能少 ...

随机推荐

  1. 记录一个i变量引发的事故

    概述 近期开发中遇到一个特别的问题,觉得很有必要与你下来.就是由于在开发中一个很小的疏忽,导致了很大的问题,是什么呢? 现象 我的程序突然引发了v8内部的错误,提示都是c++的,如下.程序一启动就直接 ...

  2. Canvas 线性图形(二):圆形

    函数 arc(x, y, radius, startAngle, endAngle, counterclockwise) 参数名 描述 x.y 圆心坐标轴 radius 圆的半径 startAngle ...

  3. 论文解读(PairNorm)《PairNorm: Tackling Oversmoothing in GNNs》

    论文信息 论文标题:PairNorm: Tackling Oversmoothing in GNNs论文作者:Lingxiao Zhao, Leman Akoglu论文来源:2020,ICLR论文地址 ...

  4. LOJ#2014「SCOI2016」萌萌哒(倍增,并查集优化连边)

    题面 点此看题 题意很明白,就不转述了吧. 题解 题目相当于告诉了我们若干等量关系,每个限制 l 1 , r 1 , l 2 , r 2 \tt l_1,r_1,l_2,r_2 l1​,r1​,l2​ ...

  5. ARC120F Wine Thief (组合数学)

    题面 有一个长为 N N N 的序列,相邻的两个数中只能选一个,总共选 k k k 个数,一种方案的价值为选的 k k k 个数的和,问所有合法方案的价值总和,答案对 998244353 取模. 1 ...

  6. Rsync数据备份工具

    Rsync数据备份工具 1.Rsync基本概述 rsync是一款开源的备份工具,可以在不同主机之间进行同步(windows和Linux之间 Mac和 Linux Linux和Linux),可实现全量备 ...

  7. DS

    树状数组 原始问题 \(a_x \overset+\gets y\) \(\sum\limits_{i=1}^{r} a_i\) 解决方法: 定义 \({\rm lb}(i) = i-i \wedge ...

  8. KingbaseES V8R6C6备份恢复案例之---单实例sys_baackup.sh备份

    案例说明: KingbaseES V8R6C6中sys_backup.sh在通用机单实例环境,默认需要通过securecmdd工具以及kingbase和root用户之间的ssh互信,执行备份初始化(i ...

  9. picoCTF:keygenme-py 解题思路

    keygenme-py 解题思路 题目如下 点击 keygenme-trial.py 获取要破解的文件 py文件代码为 点击查看代码 #================================ ...

  10. web前端小知识 —— 【HTML,CSS,JS】集锦 【第一期】 { }

    1.获取元素样式属性的方法 第 一 种 : 较灵活,能获取传进来想获取的元素的样式属性,返回的是[字符串] function getStyle(obj, name) { // IE // 主流 ret ...