Garbage Collection
The Garbage Collection process manages your application's allocation and release of memory. Garbage Collection is an automatic process that works on a Managed Heap only; it uses an Optimization Engine internally. This optimization engine determines the best time to perform a collection. Allocating Memory: When you initialize a new process, the runtime reserves a region of address space on the managed heap for processing. As objects get created, memory is allocated contiguously. Each object generated will have a reference pointer on the stack called the Root. A root includes static fields, local variables and parameters on a thread's stack, and CPU registers. As long as address space is available, the system continues to allocate space for new objects in this manner. Releasing Memory: Every application has a set of roots. Each root either refers to an object on the managed heap or is null. Releasing memory has three phases:- Marking Phase: Garbage Collection periodically examines the heap, creating a graph containing a list of all objects that are reachable from the roots. Objects not in the graph are unreachable and are considered garbage; the associated memory can be released and reclaimed for reuse.
- Relocating Phase: The references of all the objects that were on the list of all the live objects are updated to point to the new location where the objects will be relocated to in the compacting phase.
- Compacting Phase: The heap gets compacted in the compacting phase as the space occupied by the dead objects is released, and the remaining live objects are moved. All the live objects that remain after the garbage collection are moved toward the older end of the heap memory in their original order. The compacting phase moves objects that have survived a garbage collection toward the older end of the segment.
- The system has low physical memory, or there is a lack of available memory.
- The memory used by objects on the managed heap surpasses an acceptable threshold. This threshold is continuously adjusted as the process runs.
- The GC.Collect() is called, and in almost all cases, you do not have to call this method because the garbage collector runs continuously. This method is primarily used in unique situations and testing.
Objects are categorized by size. Objects greater than 85KB in size are considered Long-Lived, and the rest as Short-Lived. Long-Lived objects are stored on a separate heap called Large Object Heap - LOH, also referred to as generation 3. Moving Large objects around in the memory is very time-consuming. Therefore the GC never moves large objects; it simply removes them when they are no longer needed. Consequently, memory holes are formed in the large object heap, causing memory fragmentation. Short-Lived objects are stored and managed in three generations: 0, 1, and 2, and each generation has its own heap that is used for storing allocated objects.
- Generation 0: The garbage collector stores all new short-lived objects in generation 0. Objects often don't live past the first generation. The garbage collector performs a collection when generation 0 is full. Because it is faster to compact a portion of the managed heap than the entire heap, the garbage collector tries to release the memory in a specific generation rather than the entire heap. A collection of generation 0 alone often reclaims enough memory to allow the application to continue creating new objects. The garbage collector then promotes these compacted objects to generation 1. Because objects that survive collections tend to have longer lifetimes, it makes sense to promote them to a higher generation. Generation 0 is quick to collect because its associated heap is small.
- Generation 1: Because objects that survive collections. The objects in this generation are a buffer between the short-lived objects in generation 0 and the long-lived objects in generation 2. Gen1 collections are also quick because their associated heap is also small.
- Generation 2: Objects that survived collections in Gen1 are moved to Gen2. The objects in generation 2 are long-lived such as static objects, as they remain in the heap memory for the whole process duration. A generation 2 garbage collection is also known as a full garbage collection because it reclaims all objects from all generations.
- Avoid large object allocations
Large objects are usually arrays - Avoid memory leaks
When memory leaks occur, the objects remain referenced even if they are no longer being used. - Avoid using the GC.Collect method
When you call the GC.Collect() method, it triggers a blocking garbage collection across all generations. Thus a call to the GC.Collect() method is a time-consuming and resource-intensive operation that should be avoided. - Use structs instead of classes
- Avoid using finalizers
Whenever you have a destructor in your class the runtime treats it as a Finalize() method. As finalization is costly, you should avoid using destructors and finalizers in your classes. An instance of a class that contains a finalizer is automatically promoted to a higher generation since it cannot be collected in generation 0. If an object has a finalizer, it is not immediately removed when the garbage collector decides it is no longer 'live'. Instead, it becomes a special kind of root until .NET has been called the finalizer method. This means that these objects usually require more than one garbage collection to be removed from memory, as they will survive the first time they are found to be unused. - Use StringBuilder to reduce allocations
Strings are immutable. So whenever you add two string objects, a new string object is created that holds the content of both strings. You can avoid the allocation of memory for this new string object by taking advantage of StringBuilder. However, you should keep in mind that regular concatenations are faster than StringBuilder for a small number of concatenations.
- Large server programs are known to have heaps in the 10s of GBs.
- The low Memory Address is located at the bottom, while the High Memory Address is at the top of the stack. The newest objects are created at a higher memory address (Top), while the oldest memory objects are at the lowest memory address within the heap (Bottom).
Ginger CMS
the future of cms, a simple and intuitive content management system ... ASP.NET MVC Application
best practices like Repository, LINQ, Dapper, Domain objects ... CFTurbine
cf prototyping engine, generates boilerplate code and views ... Search Engine LITE
create your own custom search engine for your web site ... JRun monitor
monitors the memory footprint of JRun engine and auto-restarts a hung engine ... Validation Library
complete validation library for your web forms ...
the future of cms, a simple and intuitive content management system ... ASP.NET MVC Application
best practices like Repository, LINQ, Dapper, Domain objects ... CFTurbine
cf prototyping engine, generates boilerplate code and views ... Search Engine LITE
create your own custom search engine for your web site ... JRun monitor
monitors the memory footprint of JRun engine and auto-restarts a hung engine ... Validation Library
complete validation library for your web forms ...