TGViewer
C# Heppard C# Heppard @csharp_gepard · 1.65K subscribers
Post #130 2.25K

Forwarded from .NET epeshk blog

🤡 Clown Object Heap — очередная новая куча в .NET 9 для вопросов на собеседованиях

Объекты в .NET делятся по четырём кучам. С двумя старыми приходится работать постоянно, про две относительно новые обычно вспоминают только на собесах (зачем про них спрашивают?)

Small Object Heap — обычная куча для объектов, разделённая на 3 поколения — нулевое, первое, и второе. С каждой сборкой мусора, выживший объект продвигается в следующее поколение. Сборки мусора в нулевом поколении быстрые и частые, во втором — медленные, блокирующие, редкие. Во время блокирующих сборок мусора содержимое SOH компактится (живые объекты копируются подряд, чтобы между ними не было дырок и память использовалась эффективно, ссылки на эти объекты обновляются, для этого и нужна блокировка потоков)

Large Object Heap — куча для больших объектов. Отличается тем, что по-умолчанию не компактится, т.к. копировать большие объекты долго. Иногда LOH считают абсолютным злом, но без него GC паузы при сборке мусора второго поколения стали бы совсем неприличными.

Основная проблема, связанная с LOH — фрагментация. Если аллоцировать короткоживущие объекты в LOH, особенно если размер объектов разный, после сборок мусора в LOH будут оставаться дырки. Далее окажется, что эти дырки слишком маленькие, чтобы заполнить их новыми объектами и программа начнёт раздуваться по памяти. Обычно проблема решается переиспользованием объектов

- в LOH попадают объекты размером >= 85000 байт
- в основном в LOH хранятся массивы, т.к. другие большие объекты в реальности не встречаются. Тем не менее, вручную можно сделать объект-не массив, который попадёт в LOH:
[StructLayout(LayoutKind.Sequential, Size = 84977)]
class LOHject { int _; }

Console.WriteLine(GC.GetGeneration(new LOHject())); // 2

- в доисторическом фреймворке в LOH также попадают массивы double от 1000 элементов. Сделано этого для оптимизации работы с double на 32-битных системах, т.к. объекты в LOH на них выравнены по границе 8 байт. Этот факт полезен только на собеседованиях и квизах на конференциях
- можно попросить сборщик мусора скомпактить LOH:
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;

- При запуске программы с memory limit LOH не может употребить всю доступную память. OutOfMemory случится до достижения лимита
- Популярные причины аллокаций в LOH: промежуточные коллекции, создаваемые внутри Linq методов, MemoryStream

Pinned Object Heap (.NET 5) — куча, объекты в которой сборщик мусора гарантированно никогда не перемещает. В ней нет аналога CompactOnce и нет требований к размеру объекта. Нужна для массивов, указатели на которые передаются в нативный код.

Аллокация подобных объектов в обычной куче и их пиннинг (запрет на перемещение) через fixed или GCHandle создаёт проблемы для компактящего сборщика мусора. Поэтому для них сделали отдельную кучу.

Также ходят легенды, что доступ к массиву через указатель без bound checks (проверок на выход за границу массива) быстрее, но это скорее легенда, приводящая к багам, чем реальность.

Через публичный API в Pinned Object Heap можно создавать только массивы:
GC.AllocateArray<int>(128, pinned: true);
GC.AllocateUninitializedArray<int>(128, pinned: true);


Объекты в POH собираются сборщиком мусора, и при неаккуратном использовании POH может стать фрагментированным.

Frozen Object Heap (NonGC Object Heap. .NET 8) — куча для объектов, которые живут всё время жизни программы, никогда не собираются сборщиком мусора, не ссылаются на объекты вне FOH, и никогда не изменяются. В ней хранятся объекты, создаваемые рантаймом дотнета: строковые литералы, объекты Type, Array.Empty<>(), ... Публичного API для создания объектов в FOH нет. Нужна для оптимизаций — 1) GC не просматривает эти объекты, 2) JIT может генерировать более эффективный код, зная что объект никуда не переместится, не изменится, и что о новых ссылках на него не нужно сообщать сборщику мусора

@epeshkblog
  • 👍 25
  • ❤ 11
  • 🗿 2
More from @csharp_gepard
  1. Mar 13, 2026Ozon Tech Community .NET Meetup 24 марта, лофт Casa Picassa, 19:00 Ищем способы бороться с…
  2. Jan 20, 2026Ещё одна история про память #отдых Судя по комментариям специалистов и ценам на RAM в мага…
  3. Nov 25, 2025FastEnum #скорость Иногда нам нужно не просто быстро, а очень быстро. В этот момент в дело…
  4. Nov 20, 2025UnsafeAccessor #скорость Иногда возникает странное желание изменять приватные поля в класс…
  5. Nov 17, 2025Latency numbers every programmer should know Я всё время теряю эти циферки, особенно когда…
  6. Oct 29, 2025Dictionary.TryGetValue #скорость Уж сколько лет прошло и, вроде, все это знают. Но, тем не…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →