Skip to content

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

Closed

Description

@ltsbkuster

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

Activity

  1. changed the title [-]Temporary use of JsonSerializerOptions slow down JsonSerializer.Serialize[/-] [+]Temporary use of JsonSerializerOptions slows down Performance of JsonSerializer.Serialize[/+] on Jul 9, 2020
  2. removed
    untriagedNew issue has not been triaged by the area owner
    on Jul 10, 2020
  3. added this to the 5.0.0 milestone on Jul 10, 2020
  4. layomia commented on Jul 10, 2020

    @layomia
    Contributor

    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

  5. ghost locked as resolved and limited conversation to collaborators on Dec 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions