Friday, 18 February 2011

Garbage collection in .NET – large and small object heap differences.

As promised in my previous post, I’ve just uploaded source code to codeplex ( which demonstrates the differences between the large and small object heaps and how allocating memory to the large object heap needs to be considered in applications that shifts large quantities of data around.

In this project you will find 4 main tests (not unit tests, I created this as a build and run console application);

  • TestInterlacedMemoryAllocationResultsInOutOfMemory
  • TestNonInterlacedMemoryAllocationDoesNotResultInOutOfMemory
  • TestInterlacdMemoryAllocationWithFullReleaseDoesNotResultInOutOfMemory
  • TestSmallObjectHeapInterlacedAllocationDoesCompaction


This test demonstrates one of the fundamental considerations of the large object heap. You will recall from my previous post that objects that are greater than 85000 bytes will be allocated onto the large object heap (LOH) instead of the small object heap (SOH) and the LOH does not compact memory when it collects unused memory. Rather it leaves behind holes. As such, allocating memory in a manner that is interleaved and then releasing every other block will leave small holes behind.

The net result of this is the application has lots of free memory overall, but it’s only available in small chunks. As allocations require the object being allocated to be laid out in memory in one contiguous block, trying to allocate an object that would appear to still fit in memory will fail as there is no hole in the LOH big enough to accommodate it. The result in this test is an out of memory exception;


The second test does exactly the same as the first, but rather than interlacing the memory it tries to allocate larger chunks together which means when one list of data is released and cleaned up, the allocation of large objects continues to function as there are holes in the LOH big enough to accommodate;


This test attempts to prove the reason that the first test fails with an OutOfMemory exception is because of the fragmentation – it does exactly the same as the first test, but releases both lists and sure enough, as expected, the further allocation succeeds.


For completeness I included this test to prove the difference between the SOH and the LOH. It does the same as the first test, allocates memory until it’s full by interleaving objects in two lists and then frees one list. (The objects are smaller to ensure they get allocated to SOH not LOH). As you will see, this test successfully allows memory to be allocated after just one list is freed because the garbage collector performs the compaction phase on the SOH, reshuffling memory to close the holes.


Get the source code here:

No comments:

Post a Comment