为了在 .NET 9
平台上对比 Newtonsoft.Json
和 System.Text.Json
的序列化与反序列化的性能,我们可以使用 BenchmarkDotNet
来进行压测。
此处为了方便对比,我会创建两个类:
JsonOperations.cs
:JSON
序列化和反序列化操作类;JsonBenchmark.cs
:序列化操作基准测试类;以下是一个完整的示例代码,它将帮助你创建一个基准测试项目来比较这两种 JSON
序列化库的性能。
首先,请确保你的项目中已经添加了相应的 NuGet
包引用:
Newtonsoft.Json
(版本 13.0.3
)dotnet add package Newtonsoft.Json --version 13.0.3
System.Text.Json
(版本 9.0.6
)dotnet add package System.Text.Json --version 9.0.6
BenchmarkDotNet
基准测试包dotnet add package Datadog.Trace.BenchmarkDotNet --version 2.61.0
控制台 .csproj
项目结构如下:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>ExeOutputType>
<TargetFramework>net9.0TargetFramework>
<ImplicitUsings>enableImplicitUsings>
<Nullable>enableNullable>
<PublishAot>truePublishAot>
<InvariantGlobalization>trueInvariantGlobalization>
PropertyGroup>
<ItemGroup>
<PackageReference Include="Datadog.Trace.BenchmarkDotNet" Version="2.61.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.Text.Json" Version="9.0.6" />
ItemGroup>
Project>
JsonOperations
// ========================================
// JsonOperations 序列化和反序列化操作类
// ========================================
using System.Text.Json;
namespace BenchmarkTest.examples.Json;
internal class JsonOperations
{
public string SerializeWithSystemTextJson(object obj)
{
return JsonSerializer.Serialize(obj);
}
public T DeserializeWithSystemTextJson<T>(string json)
{
return JsonSerializer.Deserialize<T>(json);
}
public string SerializeWithNewtonsoftJson(object obj)
{
return Newtonsoft.Json.JsonConvert.SerializeObject(obj);
}
public T DeserializeWithNewtonsoftJson<T>(string json)
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(json);
}
}
JsonBenchmark
// ===========================================
// JsonBenchmark 序列化和反序列化操作基准测试类
// ===========================================
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Running;
using Datadog.Trace.BenchmarkDotNet;
namespace BenchmarkTest.examples.Json;
[DatadogDiagnoser]
[MemoryDiagnoser]
public class JsonBenchmark
{
private readonly JsonOperations _jsonOps = new();
private static readonly object _testObject = new { Name = "Test", Value = 123 };
private readonly ApiResponse _apiResponse = new(true, 200, "ok", _testObject);
private string _systemTextJsonSerializedObject = string.Empty;
private string _newtonsoftJsonSerializedObject = string.Empty;
private string _systemTextJsonSerializedApiResponse = string.Empty;
private string _newtonsoftJsonSerializedApiResponse = string.Empty;
[GlobalSetup]
public void Setup()
{
_systemTextJsonSerializedObject = _jsonOps.SerializeWithSystemTextJson(_testObject);
_newtonsoftJsonSerializedObject = _jsonOps.SerializeWithNewtonsoftJson(_testObject);
_systemTextJsonSerializedApiResponse = _jsonOps.SerializeWithSystemTextJson(_apiResponse);
_newtonsoftJsonSerializedApiResponse = _jsonOps.SerializeWithNewtonsoftJson(_apiResponse);
}
[Benchmark]
public string SystemTextJsonSerialize_Object() => _jsonOps.SerializeWithSystemTextJson(_testObject);
[Benchmark]
public object SystemTextJsonDeserialize_Object() => _jsonOps.DeserializeWithSystemTextJson<object>(_systemTextJsonSerializedObject);
[Benchmark]
public string NewtonsoftJsonSerialize_Object() => _jsonOps.SerializeWithNewtonsoftJson(_testObject);
[Benchmark]
public object NewtonsoftJsonDeserialize_Object() => _jsonOps.DeserializeWithNewtonsoftJson<object>(_newtonsoftJsonSerializedObject);
[Benchmark]
public string SystemTextJsonSerialize_ApiResponse() => _jsonOps.SerializeWithSystemTextJson(_apiResponse);
[Benchmark]
public object SystemTextJsonDeserialize_ApiResponse() => _jsonOps.DeserializeWithSystemTextJson<ApiResponse>(_systemTextJsonSerializedApiResponse);
[Benchmark]
public string NewtonsoftJsonSerialize_ApiResponse() => _jsonOps.SerializeWithNewtonsoftJson(_apiResponse);
[Benchmark]
public object NewtonsoftJsonDeserialize_ApiResponse() => _jsonOps.DeserializeWithNewtonsoftJson<ApiResponse>(_newtonsoftJsonSerializedApiResponse);
public static void Run(IConfig config)
{
var summary = BenchmarkRunner.Run<JsonBenchmark>(config);
Console.WriteLine(summary);
}
}
// 模拟强类型对象数据
public record ApiResponse(bool Success, int Code, string Message, object Data);
Program.cs
中运行基准测试using BenchmarkDotNet.Configs;
using BenchmarkTest.examples.Json;
using Datadog.Trace.BenchmarkDotNet;
Console.WriteLine("Hello, BenchmarkDotNetTest!");
var config = DefaultConfig.Instance.WithDatadog();
JsonBenchmark.Run(config);
在项目根目录,使用 pwsh
终端输入命令:
dotnet run -c Release
输出信息:
以下是对 BenchmarkDotNet
测试结果的详细分析:
根据提供的测试信息,我们可以从以下几个方面对 Newtonsoft.Json
和 System.Text.Json
的序列化与反序列化的性能进行详细分析:
v0.13.2
Windows 11 (10.0.26100.4484)
9.0.301
.NET 9.0.6 (9.0.625.26613)
,使用 X64 AOT AVX2
指令集这些信息表明,基准测试是在一个较为先进的硬件和软件环境中进行的,能够提供可靠的性能评估。
方法 | 平均耗时 (Mean) | 内存分配 (Allocated) |
---|---|---|
SystemTextJsonSerialize_Object |
296.8 ns | 80 B |
NewtonsoftJsonSerialize_Object |
502.5 ns | 1392 B |
分析:
System.Text.Json
在序列化操作中表现明显优于 Newtonsoft.Json
。它的平均耗时仅为 296.8 纳秒,而 Newtonsoft.Json
需要 502.5 纳秒。System.Text.Json
分配了 80 字节,而 Newtonsoft.Json
分配了 1392 字节。这说明 System.Text.Json
在内存管理上更加高效。方法 | 平均耗时 (Mean) | 内存分配 (Allocated) |
---|---|---|
SystemTextJsonDeserialize_Object |
611.2 ns | 256 B |
NewtonsoftJsonDeserialize_Object |
1,299.3 ns | 3624 B |
分析:
System.Text.Json
的反序列化操作同样优于 Newtonsoft.Json
,其平均耗时为 611.2 纳秒,而 Newtonsoft.Json
需要 1299.3 纳秒。System.Text.Json
分配了 256 字节,而 Newtonsoft.Json
分配了 3624 字节。这表明 System.Text.Json
在反序列化时也具有更低的资源消耗。方法 | 平均耗时 (Mean) | 内存分配 (Allocated) |
---|---|---|
SystemTextJsonSerialize_ApiResponse |
758.4 ns | 488 B |
NewtonsoftJsonSerialize_ApiResponse |
954.4 ns | 1688 B |
分析:
System.Text.Json
仍然保持优势。它的平均耗时为 758.4 纳秒,而 Newtonsoft.Json
需要 954.4 纳秒。System.Text.Json
分配了 488 字节,而 Newtonsoft.Json
分配了 1688 字节。方法 | 平均耗时 (Mean) | 内存分配 (Allocated) |
---|---|---|
SystemTextJsonDeserialize_ApiResponse |
1,145.0 ns | 424 B |
NewtonsoftJsonDeserialize_ApiResponse |
2,476.1 ns | 4272 B |
分析:
System.Text.Json
的平均耗时为 1145.0 纳秒,而 Newtonsoft.Json
需要 2476.1 纳秒。System.Text.Json
分配了 424 字节,而 Newtonsoft.Json
分配了 4272 字节。这表明 System.Text.Json
在处理复杂结构时依然具有显著的性能优势。System.Text.Json
在所有测试场景中都表现出比 Newtonsoft.Json
更高的性能,无论是简单的对象级别还是复杂的 API
响应级别。System.Text.Json
在内存分配方面远低于 Newtonsoft.Json
,这使得它在高并发或资源受限的环境中更具优势。JSON
序列化/反序列化操作,并且不需要 Newtonsoft.Json
提供的一些高级功能(如支持更多类型、更灵活的配置等),那么推荐使用 System.Text.Json
。SystemTextJsonDeserialize_Object
中有 3 个异常值被移除。这些异常值可能会影响最终结果的准确性,但基准测试工具已经自动处理了这些问题。Mean
表示平均耗时,Error
和 StdDev
分别表示误差范围和标准差,它们用于衡量测量的可靠性。较小的标准差意味着测试结果更加稳定。通过上述分析,可以看出 System.Text.Json
是当前 .NET 9
平台上更优的选择,特别是在性能和内存效率方面。