Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Temporary use of JsonSerializerOptions slows down Performance of JsonSerializer.Serialize #38982

Closed
ltsbkuster opened this issue Jul 9, 2020 · 1 comment
Labels
Milestone

Comments

@ltsbkuster
Copy link

Description

When using JsonSerializerOptions in a temporary fashion, like alway instantiating a new Object when a Serialization is needed, a massive decrease in Performance can be noticed.

Configuration

.NET Core SDK (reflecting any global.json):
 Version:   3.1.301     
 Commit:    7feb845744  

Runtime Environment:    
 OS Name:     Windows   
 OS Version:  10.0.18362
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\3.1.301\

Host (useful for support):
  Version: 3.1.5
  Commit:  65cd789777

.NET Core SDKs installed:
  3.1.101 [C:\Program Files\dotnet\sdk]
  3.1.301 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]


Data

This loops of 100'000 serializations of a very simple object takes more than 40 seconds on a i7-8665U in several runs.

var start = DateTime.Now;
var data = new MessageItem { Message = "simple message" };
for (var i = 0; i < 100000; i++)
{
    var dataStr = JsonSerializer.Serialize(data, new JsonSerializerOptions { IgnoreNullValues = true });
}

Console.WriteLine(DateTime.Now - start); 

Note: it is also slow if IgnoreNullValues is omitted and plain Options are passed.

If I take out the new creation of JsonSerializerOptions the loop takes 87 milliseconds, resulting in 459x better performance:

var start = DateTime.Now;
var options = new JsonSerializerOptions { IgnoreNullValues = true };
for (var i = 0; i < 100000; i++)
{
    var dataStr = JsonSerializer.Serialize(data, options);
}
Console.WriteLine((DateTime.Now - start).TotalMilliseconds);

A complete Repo is here : https://github.com/ltsbkuster/dotnet.jsonserializeroptionsperformance

@ltsbkuster ltsbkuster added the tenet-performance Performance related issue label Jul 9, 2020
@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added area-System.Text.Json untriaged New issue has not been triaged by the area owner labels Jul 9, 2020
@ltsbkuster ltsbkuster changed the title Temporary use of JsonSerializerOptions slow down JsonSerializer.Serialize Temporary use of JsonSerializerOptions slows down Performance of JsonSerializer.Serialize Jul 9, 2020
@layomia layomia removed the untriaged New issue has not been triaged by the area owner label Jul 10, 2020
@layomia layomia added this to the 5.0.0 milestone Jul 10, 2020
@layomia
Copy link
Contributor

layomia commented Jul 10, 2020

This behavior is understood and expected. The serializer undergoes a warm-up phase during the first (de)serialization of every type in the object graph when a new options instance is passed to it. This warm-up includes creating a cache of metadata it needs to perform (de)serialization: funcs to property getters, setters, ctor arguments, specified attributes etc. This metadata caches is stored in the options instance. This process is not cheap, and it is recommended to cache options instances for reuse on subsequent calls to the serializer to avoid unnecessarily undergoing the warm-up repeatedly.

On a somewhat related note, we are working on build-time code generation for JSON serialization with the aim of reducing the cost of first-time (de)serialization, and other benefits - #1568. We'll share more about this effort as the work progresses. cc @kevinwkt

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants