Ответ
Разделение на Large Object Heap (LOH) и Small Object Heap (SOH) в .NET оптимизирует управление памятью и производительность сборки мусора (GC). Объекты размером ≥85 КБ размещаются в LOH, меньшие — в SOH.
Основные причины разделения:
- Минимизация фрагментации: Перемещение (компактирование) крупных объектов при сборке мусора — дорогая операция, которая может привести к сильной фрагментации кучи. LOH по умолчанию не компактируется (хотя в .NET 4.5.1+ появилась возможность принудительной компактировки через
GCSettings.LargeObjectHeapCompactionMode). - Оптимизация производительности: Выделение памяти для больших объектов в LOH происходит иначе — без частых операций копирования между поколениями (Gen0, Gen1), что снижает накладные расходы GC.
Пример на C#:
// Попадает в SOH (размер < 85 КБ)
byte[] smallArray = new byte[10_000];
// Попадает в LOH (размер ≥ 85 КБ)
byte[] largeArray = new byte[100_000];
Важные особенности LOH:
- Очистка LOH происходит только во время сборки мусора поколения 2 (Full GC).
- Частое создание и освобождение крупных объектов может привести к фрагментации LOH и, как следствие, к исключению
OutOfMemoryException, даже если общий объем свободной памяти достаточен.