微软终于追上了?

图片来自 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. 利用 Word 表格对文字、图文进行排版

    在以前,Web 前端工程师利用 <table /> 元素对网页布局进行排版,但是如今却不推荐此元素排版了,而是改用 <div /> 元素和 CSS 弹性布局(或网格布局)对网页 ...

  2. 【AGC】如何使用认证服务与云数据库处理用户信息

    ​使用场景 华为 AGC认证服务可以为应用快速构建安全可靠的用户认证系统,可以实现多种方式关联认证登录.而如何处理这些多种登录方式的用户信息,例如在应用中发布一个活动,哪些用户参加了哪一个活动,这些信 ...

  3. KingbaseES V8R6集群维护案例之---停用集群node_export进程

    案例说明: 在KingbaseES V8R6集群启动时,会启动node_exporter进程,此进程主要用于向kmonitor监控服务输出节点状态信息.在系统安全漏洞扫描中,提示出现以下安全漏洞: 对 ...

  4. 如何修改SAO用户密码

    KingbaseES SAO 用户是专门用于审计管理的用户,用户配置审计策略需要使用该用户.在initdb 完成后,SAO  用户的默认密码保存在参数 sysaudit.audit_table_pas ...

  5. 开源即时通讯GGTalk 8.0发布,增加Linux客户端,支持在统信UOS、银河麒麟上运行!

    GGTalk在2021年推出7.0后,经过一年多时间的开发,终于推出8.0版本,实现了Linux客户端. 这几年,信创国产化的势头越来越猛,政府事企业单位都在逐步转向使用国产OS.国产CPU.国产数据 ...

  6. [C/C++]C语言-踩坑记录

    很久没写C语言的代码,发现很多小细节,记下来备查. 0. C语言常规头文件 #include <stdlib.h> #include <stdio.h> 1. 二维数组的开辟和 ...

  7. Docker(一):初识

    1.什么是Docker   Docker 是一个基于Go 语言并遵从Apache2.0协议开源的.轻量级的容器引擎,主要运行于 Linux 和 Windows,用于创建.管理和编排容器.可以让开发者打 ...

  8. Django 运行报异常:AttributeError: 'str' object has no attribute 'get'

    Technorati Tags: Python,Django,Web 在使用django.contrib.auth用户机制进行用户的验证.登录.注销操作时,遇到这个异常. 首先是写了一个登录的视图,要 ...

  9. 第六章:Django 综合篇 - 16:Authentication

    Django自带一个用户认证系统,用于处理用户账户.群组.许可和基于cookie的用户会话. Django的认证系统包含了身份验证和权限管理两部分.简单地说,身份验证用于核实某个用户是否合法,权限管理 ...

  10. Compose 命令说明

    命令对象与格式 对于 Compose 来说,大部分命令的对象既可以是项目本身,也可以指定为项目中的服务或者容器.如果没有特别的说明,命令对象将是项目,这意味着项目中所有的服务都会受到命令影响. 执行 ...