"Какие типы памяти существуют в .NET?" Этот вопрос часто встречается на собеседованиях, так как подводит к более широкой теме - управление памятью. Разберемся, как устроена память в .NET.
🏗 Устройство памяти в .NET
В CLR существуют два основных типа памяти для хранения экземпляров типов: стэк и управляемая куча.
Стэк
Стэк - это быстрая память, которая используется для хранения экземпляров значимых типов и ссылок на экземпляры ссылочных типов в куче, во время выполнения методов. Под стэк резервируется сегмент оперативной памяти, не нужно путать со стэками процессора.
Управляемая куча
Управляемая куча - это память, которая используется для хранения экземпляров ссылочных и упакованных значимых типов.
Существует четыре управляемых кучи:
- Small Object Heap (SOH) - куча маленьких объектов или просто куча. Используется для хранения экземпляров ссылочных типов, которые не хранятся в других кучах.
- Large Object Heap (LOH) - куча больших объектов. Используется для хранения экземпляров ссылочных типов размером более 85000 байт и массивов double размером больше 1000 элементов.
- Pined Object Heap (POH) - куча закрепленных объектов. Используется для хранения экзепляров закрепленных объектов. Нужна для повышения производительности при работе с ними.
- Frozen Object Heap (FOH) - куча замороженных объектов. Используется для хранения объектов, которые никогда не изменятся: конфигурации, строковые константы, кэшированные данные. Эти объекты исключены из процесса сборки мусора, что ускоряет общую производительность.
Разберем SOH и LOH подробнее, так как остальные используются редко.
При хранении объекта в управляемой куче у него есть системные поля:
- Type Handle - указатель на таблицу виртуальных методов. Позволяет определить тип объекта.
- Sync Block Index - индекс блока синхронизации. Используется для синхронизации во время блокировок. Без него нельзя было бы вызывать lock на экзепляре ссылочного типа.
Каждый из них занимает дополнительную память. Она равна размеру указателя в операционной системе: 4 байта для x32 и 8 байт для x64.
📦 Устройство SOH
Small Object Heap (SOH) - куча малых объектов или просто куча.
SOH представляет собой сегмент непрерывной памяти, внутри разделенный на поколения:
| 2 поколение | 1 поколение | 0 поколение | свободная память |
Поколения нужны для оптимизации сборки мусора: выполнить сборку в части кучи быстрее, чем во всей куче. После выполнения цикла сборки несобранные объекты перемещаются в следующее поколение. Движение всегда идет влево, т. е. из 0 в 1, из 1 во 2.
В 0 поколении находятся объекты, не подвергавшиеся сборке мусора. Во втором поколении находятся долгоживущие объекты, которые пережили две сборки мусора. Они будут существовать всё время жизни приложения, с большой вероятностью.
Новые объекты создаются в нулевом поколении. Если памяти в нулевом поколении недостаточно, выполняются следующие шаги:
- Выполняется поиск доступного сегмента памяти. Если его нет, то CLR пытается расширить нулевое поколение за счет зарезервированной памяти.
- Начинается сборка мусора.
- Выбрасывается OutOfMemoryException, и приложение завершается, если доступной памяти нет.
При успешном выполнении шага, следующий не выполняется.
📈 Устройство LOH
Large Object Heap (LOH) - это специальная область памяти для хранения больших объектов более 85000 байт и массивов double размером больше 1000 элементов. LOH нужна для повышения производительности при работе с большим объектами в памяти.
Отличия от SOH:
- В LOH нет поколений.
При работе сборщика мусора:
- LOH не сжимается автоматически для повышения производительности. Можно выполнить сжатие вручную.
🎯 Выводы
Теперь ты знаешь, как устроена память в .NET и сможешь ответить на вопросы на собеседовании!
#техничка