Ответ
Сборка мусора (GC) в .NET — это высокооптимизированный механизм автоматического управления памятью для управляемой кучи (managed heap). Его основная цель — освобождать память, занятую объектами, которые больше не достижимы из корней приложения.
Основные принципы:
-
Поколения (Generations): Куча разделена на три поколения (Gen 0, Gen 1, Gen 2) для оптимизации.
- Gen 0: Молодые, недавно созданные объекты. Сборка здесь происходит часто и быстро, так как большинство объектов быстро становятся недостижимыми.
- Gen 1: Объекты, пережившие одну сборку Gen 0. Служит буфером между Gen 0 и Gen 2.
- Gen 2: Долгоживущие объекты (например, статические данные, кэши). Сборка здесь наиболее затратна.
- Куча больших объектов (LOH): Отдельная область для объектов > 85 КБ. Собирается вместе с Gen 2, но без компрессии по умолчанию.
-
Фазы сборки мусора:
- Пометка (Marking): GC начинает с корневых ссылок (статические поля, локальные переменные, регистры CPU) и строит граф всех достижимых объектов.
- Перемещение/Сжатие (Relocation/Compaction): (Для Gen 0/1) Выжившие объекты перемещаются в старшее поколение, освобождая непрерывный блок памяти. Указатели обновляются.
- Освобождение (Sweeping): Память, занятая непомеченными (недостижимыми) объектами, освобождается.
Практическое влияние на код:
- Краткосрочные объекты дешевы. Не бойтесь создавать их в методах — они будут собраны в быстрой сборке Gen 0.
- Долгоживущие объекты дороги. Избегайте необоснованного подъема объектов в Gen 2 (например, кэши без политики очистки).
- Реализуйте
IDisposableдля освобождения неуправляемых ресурсов (файлы, сокеты, дескрипторы). GC не управляет такой памятью.// Правильное освобождение неуправляемых ресурсов using (var fileStream = new FileStream("file.txt", FileMode.Open)) using (var reader = new StreamReader(fileStream)) { var content = reader.ReadToEnd(); } // Dispose() будет вызван автоматически, даже при исключении - Избегайте вызовов
GC.Collect()в рабочем коде. Это нарушает внутреннюю эвристику GC и обычно ухудшает производительность. Оставьте решение сборщику.
Вывод: GC в .NET — сложный и эффективный механизм. Понимание его работы помогает писать производительный код, избегая утечек памяти и излишней фрагментации.