TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.76K subscribers
Post #1820 1.5K
День 1485. #ЗаметкиНаПолях
Особенность (Производительности) JsonSerializer
System.Text.Json.JsonSerializer имеет странную особенность в отношении производительности и управления памятью. Посмотрим, что «не так» с этим кодом:
JsonSerializer.Serialize(myObject, 
new JsonSerializerOptions(...));.

JsonSerializerOptions используется для настройки сериализации и десериализации объектов. Он имеет несколько свойств, которые описывают, например, хотите ли вы иметь отступы в JSON. Теперь небольшой бенчмарк:
public record Test(string FirstName, string LastName);

[MemoryDiagnoser]
public class JsonBenchmark
{
private static readonly
JsonSerializerOptions _options = new();

public void Default()
{
for (var i = 0; i < 100; i++)
JsonSerializer.Serialize(
new Test("Steven", "Giesel"));
}

[Benchmark]
public void OptionsField()
{
for (var i = 0; i < 100; i++)
JsonSerializer.Serialize(
new Test("Steven", "Giesel"), _options);
}

[Benchmark]
public void OptionsNew()
{
for (var i = 0; i < 100; i++)
JsonSerializer.Serialize(
new Test("Steven", "Giesel"),
new JsonSerializerOptions());
}
}

Итак, у нас 3 метода. Один без опций, второй использует статическое поле, а третий – каждый раз вызывает new(). Результаты:
| Method       |  Mean    | Allocated | 
|--------------|----------|-----------|
| Default | 13.89 us | 14.06 KB |
| OptionsField | 13.89 us | 14.06 KB |
| OptionsNew | 53.36 us | 42.79 KB |

Мы видим, что создание нового экземпляра в цикле - это дорого. Очевидно, что new() требует времени и памяти. Да, но не настолько. На самом деле, если параметры не установлены, используется экземпляр по умолчанию. При передаче параметров сериализатор вызывает функцию InitializeForReflectionSerializer. Она довольно дорогая, поскольку собирает необходимую информацию о том, как выглядит ваш объект с помощью рефлексии. Если мы используем статическое поле, экземпляр инициализируется один раз, а дальше будет кэширован. При использовании new() InitializeForReflectionSerializer вызывается каждый раз.

И что?
Если вы вызываете сериализацию/десериализацию нечасто, ничего страшного. Но вы можете использовать её в Entity Framework в сочетании с ValueConverter:
protected override void OnModelCreating(ModelBuilder mb)
{
mb
.Entity<MyModel>()
.Property(e => e.MyList)
.HasConversion(
v => JsonSerializer
.Serialize(v, new JsonSerializerOptions(…)),
v => JsonSerializer
.Deserialize<List<MyType>>(
v, new JsonSerializerOptions(…)));
}

Если у вас тысячи строк, это может быть очень дорого! Лучше взять значение по умолчанию или создать статическое поле.

Источник: https://steven-giesel.com/blogPost/0e7512b0-c854-4cce-8606-765fcaf1e69c
  • 👍 20
More from @netdeveloperdiary
  1. Oct 13, 2026День 2813. #ЗаметкиНаПолях #Async Ещё Раз Про Async/Await в C#. Часть 1 1. Почему существу…
  2. Oct 12, 2026День 2812. #Карьера #AI Как Разработчикам Оставаться Полезными, Когда Код Пишет ИИ? По мер…
  3. Oct 11, 2026День 2811. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
  4. Oct 10, 2026День 2810. #ЧтоНовенького #VSCode Более Быстрый и Лёгкий C# Dev Kit Мы, разработчики, люби…
  5. Oct 9, 2026День 2809. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Окончание Начало 3.…
  6. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →