Aman Baloch

Software Engineer from Melbourne

View on GitHub
2 December 2024

.NET Performance Analysis: Newtonsoft.Json vs System.Text.Json in .NET 9

:clock3: 8 minutes read

Today, I want to talk about something that’s been on my mind lately - JSON serialization in .NET. As a passionate developer, I’m always curious about the best ways to solve problems, and JSON serialization is no exception.

Recently, I came across an article by Trevor McCubbin that compared the performance of System.Text.Json and Newtonsoft.Json in .NET 8. I was intrigued by the results, and it got me thinking - how do these two popular JSON serialization libraries stack up against each other in .NET 9?

In this article, I’ll share my findings and provide some insights into the performance and features of both System.Text.Json and Newtonsoft.Json.

Benchmark Setup

To accurately compare the performance of System.Text.Json and Newtonsoft.Json in JSON serialization, I’ll be focusing on two main use cases:

Serialization and Deserialization of a Single Large Dataset: This will provide insights into how each library handles bulk data. Serialization and Deserialization of Many Small Datasets: This will showcase how each library performs when dealing with a large number of smaller payloads. To generate diverse test data, I’ll be utilizing the Bogus NuGet package to generate random users with unique identities. This will help us evaluate how each library handles different types of data.

[GlobalSetup]
    public void GlobalSetup()
    {
        var faker = new Faker<Person>()
        .RuleFor(c => c.Name, f => f.Name.FullName())
        .RuleFor(c => c.Age, f => f.Random.Int(1, 100))
        .RuleFor(c => c.DateOfBirth, f => f.Date.Recent())
        .RuleFor(c => c.IsMarried, f => f.Random.Bool())
        .RuleFor(c => c.Children, f => f.Lorem.Words(f.Random.Int(1, 5)));

        persons = faker.Generate(Count);
        personsJson = System.Text.Json.JsonSerializer.Serialize(persons);

        personListJson = persons.Select(c => System.Text.Json.JsonSerializer.Serialize(c)).ToList();
    }

Performance

Deserialize Big Data

In this benchmark, we will compare deserialization performance of both approaches using a single large object.

[BenchmarkCategory("DeserializeBigData"), Benchmark]
public void JsonSerializer_Deserialize_BigData()
{
    _ = System.Text.Json.JsonSerializer.Deserialize<List<Person>>(personsJson);
}

[BenchmarkCategory("DeserializeBigData"), Benchmark(Baseline = true)]
public void JsonConvert_Deserialize_BigData()
{
    _ = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Person>>(personsJson);
}

Results

Method Count Mean Error StdDev Ratio RatioSD Allocated Alloc Ratio
JsonSerializer_Deserialize_BigData 10000 20.88 ms 0.394 ms 0.368 ms 0.78 0.02 3.72 MB 0.85
JsonConvert_Deserialize_BigData 10000 26.78 ms 0.535 ms 0.657 ms 1.00 0.03 4.39 MB 1.00

Just like in the .NET 8 analysis, System.Text.Json is the clear winner when it comes to deserialization performance

Deserialize Small Data Objects

In this scenario, we test the deserialization of multiple small JSON objects.

[BenchmarkCategory("DeserializeSmallData"), Benchmark]
    public void JsonSerializer_Deserialize_SmallData()
    {
        foreach (var person in personListJson)
        {
            _ = System.Text.Json.JsonSerializer.Deserialize<Person>(person);
        }
    }

    [BenchmarkCategory("DeserializeSmallData"), Benchmark(Baseline = true)]
    public void JsonConvert_Deserialize_SmallData()
    {
        foreach (var person in personListJson)
        {
            _ = Newtonsoft.Json.JsonConvert.DeserializeObject<Person>(person);
        }
    }

Results

Method Count Mean Error StdDev Ratio Allocated Alloc Ratio
JsonSerializer_Deserialize_SmallData 10000 11.36 ms 0.122 ms 0.115 ms 0.63 7.96 MB 0.26
JsonConvert_Deserialize_SmallData 10000 18.14 ms 0.222 ms 0.197 ms 1.00 30.55 MB 1.00

System.Text.Json once more demonstrates its superiority, outperforming Newtonsoft.Json in both speed and memory efficiency. Notably, it achieves this while using less than half the memory.

Serialize Big Data Object

Now lets look into serialization of big data object

[BenchmarkCategory("SerializeBigData"), Benchmark]
public void JsonSerializer_Serialize_BigData()
{
    _ = System.Text.Json.JsonSerializer.Serialize(persons);
}

[BenchmarkCategory("SerializeBigData"), Benchmark(Baseline = true)]
public void JsonConvert_Serialize_BigData()
{
    _ = Newtonsoft.Json.JsonConvert.SerializeObject(persons);
}

Results

Method Count Mean Error StdDev Ratio RatioSD Allocated Alloc Ratio
JsonSerializer_Serialize_BigData 10000 7.784 ms 0.0830 ms 0.0736 ms 0.66 0.02 2.69 MB 0.42
JsonConvert_Serialize_BigData 10000 11.788 ms 0.2297 ms 0.4022 ms 1.00 0.05 6.4 MB 1.00

Yet again, System.Text.Json performs better than Newtonsoft.Json in both execution time and memory.

Serialise Small Data Object

This is a common scenario where we serialize several small data objects to JSON.

[BenchmarkCategory("SerializeSmallData"), Benchmark]
    public void JsonSerializer_Serialize_SmallData()
    {
        foreach (var person in persons)
        {
            _ = System.Text.Json.JsonSerializer.Serialize(person);
        }
    }

    [BenchmarkCategory("SerializeSmallData"), Benchmark(Baseline = true)]
    public void JsonConvert_Serialize_SmallData()
    {
        foreach (var person in persons)
        {
            _ = Newtonsoft.Json.JsonConvert.SerializeObject(person);
        }
    }

Results

Method Count Mean Error StdDev Ratio Allocated Alloc Ratio
JsonSerializer_Serialize_SmallData 10000 7.917 ms 0.0683 ms 0.0605 ms 0.72 5.89 MB 0.33
JsonConvert_Serialize_SmallData 10000 10.990 ms 0.0766 ms 0.0717 ms 1.00 17.63 MB 1.00

And there are no surprises. System.Text.Json still outperforms Newtonsoft.Json in serializing multiple small data objects.

Features

While System.Text.Json is a more lightweight and performant option, Newtonsoft.Json has some features that may be important to your application. Here are a few examples:

However, System.Text.Json has some features that are not available in Newtonsoft.Json, such as:

Conclusion

In conclusion, System.Text.Json is a more performant and lightweight option for working with JSON in .NET 9. While Newtonsoft.Json has some features that may be important to your application.

You can download this sample code from github https://github.com/updateaman/JsonSerializerVsJsonConvert/blob/main/Program.cs

tags: json - parsing - performance