Skip to content

Instantly share code, notes, and snippets.

@sunmeat
Last active October 28, 2025 13:17
Show Gist options
  • Save sunmeat/e1785c0561ca78e5415ca29a632987fc to your computer and use it in GitHub Desktop.
Save sunmeat/e1785c0561ca78e5415ca29a632987fc to your computer and use it in GitHub Desktop.
нові фішки збирача сміття в дот нет 9

Нові можливості збирача сміття в .NET 9: Огляд адаптивних механізмів та оптимізацій продуктивності

Анотація

Збирач сміття (Garbage Collector, GC) є ключовим компонентом платформи .NET, що забезпечує автоматичне керування пам'яттю та запобігає витокам. У версії .NET 9, випущеній у листопаді 2024 року, відбулися значні покращення GC, спрямовані на підвищення ефективності пам'яті, зниження латентності та адаптацію до динамічних навантажень. Основними інноваціями є активація за замовчуванням механізму DATAS (Dynamic Adaptation to Application Sizes), адаптивний Server GC та оптимізації, пов'язані з JIT-компіляцією. Ця оглядова стаття аналізує ці зміни, їх механізми, вплив на продуктивність та рекомендації щодо використання. На основі офіційної документації Microsoft та бенчмарків, демонструється зниження споживання пам'яті на 93% та зростання throughput на 15% у типових сценаріях. Стаття корисна для розробників, які працюють з високонавантаженими додатками, особливо в хмарних та контейнеризованих середовищах.

Ключові слова: .NET 9, Garbage Collector, DATAS, Server GC, адаптивне керування пам'яттю, продуктивність, латентність.

Вступ

Історія розвитку збирача сміття в .NET сягає часів .NET Framework 1.0, де GC базувався на поколінному підході (generational GC) з двома основними режимами: Workstation GC (для клієнтських додатків) та Server GC (для серверних, з паралельними потоками). З переходом на .NET Core та .NET 5+, акцент змістився на кросплатформенність, оптимізацію для хмар (наприклад, Azure) та контейнери (Docker, Kubernetes). У .NET 8 з'явилися перші елементи адаптивності, але .NET 9 робить крок уперед, роблячи GC "розумнішим" – здатним динамічно реагувати на розмір додатка та навантаження, а не лише на апаратні ресурси.

Чому це важливо? У сучасних додатках, таких як мікросервіси чи веб-API, флуктуації навантаження призводять до неефективного використання пам'яті: фіксований heap у Server GC може "переїдати" ресурси в низьконавантажених періодах, а Workstation GC – не справлятися з багатоядерними системами. За даними TechEmpower, оптимізації .NET 9 знижують memory footprint на 93% та підвищують requests per second (RPS) на 15%. Ця стаття оглядає ключові фішки: DATAS, адаптивний Server GC, покращення латентності та інтеграцію з JIT, з прикладами та бенчмарками.

Огляд архітектури GC у .NET

Перш ніж перейти до новинок, коротко нагадаємо базову модель. GC у .NET поділяє об'єкти на покоління (Gen0 – короткоживучі, Gen1 – проміжні, Gen2 – довгоживучі, LOH – великі об'єкти). Колекція починається з Gen0, і якщо пам'ять не звільняється, переходить до старших поколінь. Server GC використовує окремі heap на ядро для паралелізму, що ідеально для серверів, але фіксований розмір (зазвичай 4x від робочого набору) призводить до надмірного споживання в контейнерах.

У .NET 9 фокус на адаптивності: GC моніторить long-lived data (довгоживучі об'єкти) та динамічно налаштовує heap, зменшуючи паузи та алокації. Це інтегровано з JIT-оптимізаціями, які зменшують кількість об'єктів, що створюються (наприклад, елімінація boxing).

DATAS: Динамічна адаптація до розміру додатка

Механізм роботи

DATAS (Dynamic Adaptation to Application Sizes) – це ключова фішка .NET 9, введена як опція в .NET 8 і активована за замовчуванням для Server GC у .NET 9. Вона динамічно налаштовує розмір heap пропорційно до обсягу long-lived data, а не фіксовано за апаратними ресурсами (CPU/пам'ять). Алгоритм моніторить:

  • Розмір Gen2 (довгоживучі об'єкти).
  • Частоту алокацій та колекцій.
  • Навантаження (throughput vs latency).

Результат: heap росте поступово, а не стрибками, що особливо корисно в контейнерах, де ресурси обмежені (наприклад, 256 MB у Kubernetes pod). У класичному Server GC heap міг сягати гігабайт навіть при низькому навантаженні; DATAS тримає його в 1.5–2x від реального робочого набору.

Переваги та бенчмарки

Тести показують:

  • Зниження memory usage: У сценарії з флуктуаційним навантаженням (k6 load testing) .NET 9 з DATAS демонструє поступовий ріст LOH (Large Object Heap), проти стрибків у .NET 8. Загальне споживання – на 50–70% менше в низьконавантажених періодах.

  • GC-паузи: Більш часті (Gen0 кожні 10–20 сек), але коротші (1–5 мс vs 10–50 мс). Розподіл пауз рівномірніший, без "спайків".

  • Throughput: +10–15% RPS у TechEmpower для веб-сервісів.

Приклад конфігурації (якщо потрібно вимкнути для максимального throughput):

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <GarbageCollectionAdaptationMode>0</GarbageCollectionAdaptationMode>
    <ServerGarbageCollection>true</ServerGarbageCollection>
  </PropertyGroup>
</Project>

У цьому режимі DATAS ігнорується, повертаючись до legacy Server GC.

Приклад використання

Уявіть ASP.NET Core API з динамічним навантаженням. Без DATAS: при піках heap розростається до 1 GB, викликаючи OOM (OutOfMemory). З DATAS: heap адаптується до 200–400 MB, з регулярними Gen0. Тест з Minikube показує: .NET 9 – 30% менше подій GC, але ефективніші.

Адаптивний Server GC: Фокус на латентності та масштабуванні

Зміни в дизайні

Server GC у .NET 9 перероблено для адаптації до вимог додатка, а не ресурсів середовища. Раніше фіксований "heap-per-core" (окремий сегмент на ядро) призводив до надмірного використання в high-core системах з малим робочим набором (наприклад, 64 ядра, але 100 MB data). Тепер GC динамічно групує сегменти, зменшуючи contention.

Ключові покращення:

  • Паралельна компакція: На Linux – vxsort у паралельному режимі, що скорочує паузи на 20–30% під час Gen2 колекцій.

  • Зниження алокацій через JIT: Елімінація boxing у ArgumentNullException.ThrowIfNull (з 2400 B до 0), Nullable<T> checks (allocation-free) та Delegate.EnumerateInvocationList (48 B → 0). Це зменшує тиск на GC на 15–25%.

  • Конкурентність: Покращена thread scheduling для багатоядерних машин, з меншим contention у concurrent collections.

Бенчмарки продуктивності

Сценарій .NET 8 (Server GC) .NET 9 (Adaptive) Покращення
TechEmpower RPS 1,000,000 req/s 1,150,000 req/s +15%
Memory footprint 1.5 GB 100 MB -93%
Gen2 pause time 50 ms 20 ms -60%
Allocation rate (low load) 100 MB/s 40 MB/s -60%

Джерело: Офіційні бенчмарки Microsoft. У контейнерах (Docker) – ще кращі результати: LOH росте лінійно, без стрибків.

Конфігурація та тюнінг

Legacy Server GC можна повернути:

<PropertyGroup>
  <ServerGarbageCollection>true</ServerGarbageCollection>
  <GCHeapHardLimit>500MB</GCHeapHardLimit>  <!-- Обмеження для контейнерів -->
</PropertyGroup>

Рекомендація: Використовуйте DATAS за замовчуванням; вимкніть лише для стабільно високого навантаження (e.g., batch processing).

Інші оптимізації: Латентність, Gen2 та інтеграція

Покращення Gen2 колекцій

Gen2 – "ахіллесова п'ята" для довгоживучих додатків. У .NET 9:

  • Enhanced Compaction: Автоматична компакція LOH для уникнення фрагментації, з parallel sorting.

  • Low-Latency Mode: Розширено для Server GC, з динамічним балансом між throughput та паузами (конфіг: GCLatencyMode.LowLatency).

Синергія з JIT та runtime

Багато фішок GC – результат JIT-оптимізацій:

  • Loop Optimizations: Downward counting loops (+12% швидкість), bounds check elision (до 76% у string.Equals).

  • SIMD/Vectorization: AVX512 для zeroing (67% швидше DoubleToUlong), що зменшує алокації.

  • Reflection Speedups: FieldInfo.GetValue – 90% швидше, знижуючи GC тиск у DI (Dependency Injection).

Приклад коду з оптимізацією (використання SearchValues<T> для пошуку, замість loops):

using System.Buffers.Text;  // .NET 9 enhancement

var searchValues = SearchValues.Create(new[] { "foo", "bar" });
if (searchValues.IndexOf("hello world") >= 0) { /* ... */ }
// 100x швидше, менше алокацій

Висновок

Нові фішки GC у .NET 9 – це еволюція від статичного до адаптивного керування пам'яттю, з DATAS як "серцем" змін. Вони роблять платформу ідеальною для сучасних сценаріїв: контейнери, мікросервіси, AI-додатки з флуктуаціями. Переваги – у зниженні memory на 93%, скороченні пауз та +15% throughput – перевищують мінімальні витрати (e.g., modest throughput drop у legacy режимах). Рекомендації: оновлюйте до .NET 9, тестуйте з BenchmarkDotNet, моніторьте через OpenTelemetry. Майбутнє – у подальшій інтеграції з AI для передбачення навантажень.

Подальші дослідження: Вплив на NativeAOT та ARM-архітектури.

Список літератури

  1. Microsoft. (2024). What's new in .NET 9 runtime.

  2. Microsoft. (2024). Performance Improvements in .NET 9.

  3. Vensas. (2025). DATAS and Server Garbage Collection in .NET 9.

  4. Microsoft. (2024). Announcing .NET 9.

  5. C# Corner. (2024). Understanding the Working of Garbage Collector in .NET 9.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment