What is the Large Object Heap, and why is it a concern?
Quick Answer
Objects of 85,000 bytes or more (mostly big arrays and strings) go on the Large Object Heap. The LOH is collected only during a Gen 2 GC (expensive) and by default is not compacted, so it fragments — free space exists but not in a contiguous block big enough for the next large allocation.
The runtime puts any allocation of about 85 KB or more on a separate heap, the LOH — think large byte arrays, big strings, buffers. Two things make it a problem. First, it's only cleaned up in a full Gen 2 collection, which is the slow kind. Second, it isn't compacted by default, so after a while you get fragmentation — plenty of total free memory but no single gap large enough, which can even throw OutOfMemory. The fix is to stop allocating large short-lived buffers: pool them with ArrayPool, or restructure to stream data in chunks rather than materialising it all at once.
- Avoid churning large buffers: reuse with
ArrayPool<T>.Shared, or stream instead of loading a whole file/response into one array. - You can force a one-off compaction:
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;— use sparingly. - Watch for hidden large allocations:
List<T>growth,MemoryStream.ToArray(), big LINQToList(), serialization buffers.