The Setup
.NET allocates memory for each generation’s heap (0, 1, 2, LOH) in segments to get a continuous block of memory, on startup, and when it attempts to satisfy an allocation request, after a collection.
This memory allocated for each heap will likely level off as the application “warms up”, except potentially for generation 2, and large object heap. During a garbage collection, each heap (0, 1, 2) is swept and compacted, except for the large object heap (LOH), which is just swept.
I understand the ‘sweep’ part of a collection to mean that the GC identifies which objects are no longer rooted and are available for collection (or finalization) and that ‘compact’ means that the addresses that are still alive in a heap are reorganized so that the available remaining heap has more continuous memory available to it.
As the budget for each segment within the heap is exceeded, .NET will allocate another segment in order to fulfill allocations if it can.
The Question
My question comes down to what happens to that memory in each heap, that is not be used by the application (committed) any longer, but is still reserved by .NET? When is it released back to the OS?.
I believe this to be the scenario where a process might appear to be consuming a lot of memory (virtual size is quite large, but private bytes small), but when inspecting its heaps are mostly free space. As another caveat, the total size of the heaps may also be quite small, and not account for the memory being consumed by the process.
There is no blocked finalizer and all looks healthy for a process - it may have been running for weeks before it triggered a monitor alert (e.g.).
Trying for further clarification of the question, if you read Tess .NET Memory Management - A Restaurant Analogy, if the tables are heap segments, does the restaurant ever lose tables (e.g. free heap segments)?
Edit
- Removed confusing reference to working set and chickens
- Added reference to Tess restaurant analogy
See Question&Answers more detail:
os