.NET Memory Management Concepts
To work with dotMemory effectively, you must have a general understanding about how .NET manages memory. The following lists summarize .NET memory concepts. For additional information, you may refer to MSDN or other materials in the Web.
- Garbage Collector (GC) is the part of the .NET framework that allocates and releases memory for your .NET applications.
- When a new process is started, the runtime reserves a region of address space for the process called the managed heap.
- Objects are allocated in the heap contiguously one after another.
- Memory allocation is a very fast process as it is just the adding of a value to a pointer.
- In addition to the managed heap, an app always consumes some amount of so-called unmanaged* memory which is not managed by GC.
*Generally, it is required by .NET Common Language Runtime itself, dynamic libraries employed by the app, graphics buffer, and so on.
- The process of releasing memory is called garbage collection.
- When GC performs a collection, it releases only objects that are no longer in use by the application (for example, a local variable in a method can be accessed only during the method execution and after this, the variable is no longer needed).
- To determine whether the object is used or not, GC examines application’s roots - strong references that are global to the application. Typically, these are global and static object pointers, local variables, and CPU registers. Learn more about possible GC roots inAnalyzing GC Roots.
- For each active root, GC builds a graph that contains all the objects that are reachable from these roots.
- If an object is unreachable, GC considers it no longer in use and removes the object from the heap (releases the memory occupied by the object).
- After the object is removed, GC compacts reachable objects in memory.
- For better performance of memory release, the managed heap is divided into segments called generations: 0, 1, and 2.
- When objects are just created, they are placed to the Generation 0 (Gen 0).
- When Gen 0 is full (the size of the heap and generations is defined by GC), GC performs a garbage collection. During the collection, GC removes all unreachable objects from the heap. All reachable objects are promoted to the Generation 1 (Gen 1).
- The Gen 0 collection is a rather quick operation.
- When Gen 1 is full, the Gen 1 garbage collection is performed. All objects that survive the collection are promoted to Gen 2. The Gen 0 collection also takes place here.
- When Gen 2 is full, GC performs full garbage collection. First, Gen 2 collection is performed, after this, the Gen 1 and Gen 0 collections take place. If there is still not enough memory for new allocations, GC raises the OutOfMemory exception.
- During full garbage collection, GC has to pass through all objects in the heap, so, this process might have a great impact on system resources.
Large Object Heap
- Due to performance reasons, large objects (>85KB) are stored in a separate segment of the managed heap called Large Object Heap (LOH).
- Survived objects in LOH are not compacted*. This means that LOH becomes fragmented over time.
*Starting from .NET Framework 4.5.1, you can force GC to compact LOH during the full garbage collection.