Large Object Heap (LOH) & Pinned Object Heap (POH)
1Concept
Objects >= 85,000 bytes allocate directly on the Large Object Heap (LOH), which is not compacted by default. The Pinned Object Heap (POH in .NET 5+) stores pinned interop buffers without fragmenting the generational heap.
2Architecture Diagram
Managed Heap Segments: ├── Small Object Heap (SOH) ──> Gen 0, Gen 1, Gen 2 (Compacted on GC) ├── Large Object Heap (LOH) ──> Objects >= 85,000 bytes (Swept, rare compaction) └── Pinned Object Heap (POH)──> Native pinned buffers (Zero heap compaction fragmentation!)
3Code Example
C# 13 & .NET 9
using System;
public class LohAndPohDemo
{
public static void Main()
{
// Allocates directly on Large Object Heap (>= 85,000 bytes)
byte[] largeArray = new byte[90_000];
Console.WriteLine($"Large Array Generation: Gen {GC.GetGeneration(largeArray)} (LOH is part of Gen 2)");
// Allocate on Pinned Object Heap (.NET 6+)
byte[] pinnedBuffer = GC.AllocateArray<byte>(1024, pinned: true);
Console.WriteLine($"Pinned Array allocated directly on POH: {GC.GetGeneration(pinnedBuffer)}");
}
}4Expected Output
Large Array Generation: Gen 2 (LOH is part of Gen 2) Pinned Array allocated directly on POH: 2
5Key Takeaways
- ✓Avoid frequent short-lived LOH allocations (>85KB); use `ArrayPool<T>` instead.
- ✓POH eliminates memory fragmentation caused by `fixed` pointers during socket I/O.
- ✓Configure `GCSettings.LargeObjectHeapCompactionMode` if LOH defragmentation is needed.