Microsoft .NET Source Generators: Speeding up JSON Serialization

One of the big features added to Microsoft .NET 5 was the addition of source generators. A Source Generator is a new kind of component that C# developers can write that lets you do two major things:

  • Retrieve a compilation object that represents all user code that is being compiled. This object can be inspected, and you can write code that works with the syntax and semantic models for the code being compiled, just like with analyzers today.
  • Generate C# source files that can be added to a compilation object during compilation. In other words, you can provide additional source code as input to a compilation while the code is being compiled.

Since my new book “Rock Your Code: Code & App Performance for Microsoft .NET” focuses on performance, I am most interested in these types of generators. In this article, I will be showing the System.Text.Json source generator.

Setting Up the Source Generator

First, we must create a new type using JsonSerializerContext as the base type to set this up. In the code below, part of the benchmarking code for my code performance book, I am creating a context type for PersonProper and List<PersonProper>. PersonProper is one of the main types I use in benchmark testing that can be found in my Spargine OOS.

using System.Text.Json.Serialization;

[JsonSourceGenerationOptions(WriteIndented = true)]

[JsonSerializable(typeof(PersonProper))]

public partial class PersonProperJsonSerializerContext : JsonSerializerContext

{

}

[JsonSourceGenerationOptions(WriteIndented = true)]

[JsonSerializable(typeof(List<PersonProper>))]

public partial class PersonProperCollectionJsonSerializerContext : JsonSerializerContext

{

}

That’s it! Easy! No need to modify the type that you will be serializing! The main property we will be using is Default as you will see.

Serializing & Deserializing

Serializing and deserializing are simple using System.Text.Json.JsonSerializer is shown below.

Serialize

Here is how to serialize an object.

var json = JsonSerializer.Serialize(person, typeof(PersonProper),
PersonProperJsonSerializerContext.Default);

Here is how to serialize a List<>.

var json = JsonSerializer.Serialize(json, typeof(List<PersonProper>),
PersonProperCollectionJsonSerializerContext.Default);

Deserialize

This is how to deserialize JSON for an object.

var person = JsonSerializer.Deserialize(json, typeof(PersonProper),
PersonProperJsonSerializerContext.Default) as PersonProper;

This is how to deserialize JSON for a List<>.

var people = JsonSerializer.Serialize(json, typeof(List<PersonProper>),
PersonProperCollectionJsonSerializerContext.Default);

Performance

This source generator’s main purpose is to increase performance. Let’s see if that is true. The first chart shows the performance of a reference object (PersonProper from Spargine).

As you can see, using the JSON source generator does improve performance and the bytes allocated.

Allocations:

  • Deserialize – 2,150 to 2,174 bytes
  • Deserialize with generator – 872 to 88 bytes
  • Serialize – 960 – 1,024 bytes
  • Serialize with generator – 1,088 to 1,176 bytes

Now let’s test serialization for a list of ref objects (PersonProper from Spargine) with a count of 100 items.

As you can see, the performance is close.

Allocations:

  • Deserialize – 91,551 to 91,766 bytes
  • Deserialize with generator – 91,393 to 91,528bytes
  • Serialize – 96,893 – 96,889 bytes
  • Serialize with generator – 117,582 to 117,700 bytes

Summary

Using the source generator does improve performance for most of the benchmark tests. I hope that the .NET team at Microsoft will make improvements.

You can find more performance tips for .NET by picking up the 3rd edition of Rock Your Code: Code & App Performance for Microsoft .NET available on Amazon.com.

Please make a comment below. I’d love to hear from you.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.