Как работает сборщик мусора (GC) в .NET?
В C# я не вызываю delete/free, память освобождается сама. Как именно работает сборщик мусора и нужно ли мне как-то на него влиять? Что за «поколения», про которые все говорят?
2 ответа
GC (Garbage Collector) — компонент CLR, который автоматически освобождает память от объектов, на которые больше никто не ссылается.
Как он понимает, что объект «мёртв»: GC строит граф достижимости от корней (статические поля, локальные переменные на стеке, регистры). Всё, до чего нельзя дойти по ссылкам, считается мусором и собирается.
Поколения — ключевая оптимизация. Большинство объектов живут очень недолго (создали в методе — выбросили). Поэтому куча делится на:
- Gen 0 — новые объекты. Собирается часто и быстро.
- Gen 1 — буфер между молодыми и старыми.
- Gen 2 — долгоживущие объекты. Собирается редко.
Пережил объект сборку Gen 0 — переезжает в Gen 1, потом в Gen 2. Идея в том, что не нужно каждый раз сканировать всю кучу.
Что делать вам: обычно ничего. Вручную дёргать GC.Collect() почти всегда вредно — вы только мешаете эвристикам рантайма. Ваша зона ответственности — неуправляемые ресурсы (файлы, соединения, сокеты): их GC не знает как чистить, поэтому реализуйте IDisposable и используйте using:
using (var stream = new FileStream("data.txt", FileMode.Open))
{
// работа с файлом
} // Dispose() вызовется автоматически, файл закроется
Или короче, начиная с C# 8:
using var stream = new FileStream("data.txt", FileMode.Open);
Дополню про частую ошибку новичков: GC чистит память, но не закрывает за вас файлы и соединения с БД вовремя. Поэтому не путайте «память освобождается сама» с «ресурсы освобождаются сами». Для второго — IDisposable/using. А GC.Collect() в проде — это почти всегда code smell.