Что такое поколение (generation) в сборке мусора .NET?

«Что такое поколение (generation) в сборке мусора .NET?» — вопрос из категории Управление памятью, который задают на 32% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Поколения (Generations) — это механизм оптимизации в сборщике мусора (Garbage Collector, GC) .NET, основанный на эмпирическом наблюдении: большинство объектов живут очень недолго (гипотеза о слабом поколении).

Куча управляемых объектов делится на три поколения:

Поколение Содержание Частота сборки
Gen 0 Вновь созданные объекты. Самый маленький по размеру. Очень часто (при нехватке памяти в Gen 0).
Gen 1 Объекты, пережившие одну сборку мусора Gen 0. Буфер между короткоживущими и долгоживущими объектами. Реже, чем Gen 0.
Gen 2 Долгоживущие объекты (например, статические поля, кэши). Наиболее редко.

Отдельно выделяется Куча больших объектов (Large Object Heap, LOH): объекты размером ≥ 85 000 байт размещаются здесь и относятся к Gen 2.

Как это работает (пример жизненного цикла объекта):

// 1. Создание нового объекта. Он размещается в Gen 0.
var shortLived = new MyClass();

// 2. Имитация нехватки памяти в Gen 0, запускается сборка мусора Gen 0.
//    Предположим, 'shortLived' все еще используется (имеет корневые ссылки).
//    Он выживает и **продвигается (promoted)** в Gen 1.
// GC.Collect(0); // (На практике вызывать GC вручную обычно не нужно)

// 3. Создаем еще один объект. Он снова попадает в Gen 0.
var anotherObject = new MyClass();

// 4. Новая сборка мусора Gen 0. 'anotherObject' уничтожается (предположим).
//    Затем, если нужно освободить больше памяти, GC может собрать и Gen 1.
//    Выживший 'shortLived' продвигается в Gen 2.

Зачем это нужно?

  • Производительность: GC тратит большую часть времени на быструю проверку маленькой кучи Gen 0, где скапливается большинство мусора, и реже затрагивает большие объемы памяти в Gen 2.
  • Локализация ссылок: Связанные объекты, созданные вместе, часто находятся рядом в памяти, что улучшает производительность кэша процессора.