TL;DR: The garbage collector (GC) manages the allocation and release of memory for an application.
Garbage Collection is an important aspect of programming developers need to be more mindful of in some languages than otherwise. In C# this is handled by the Common Language Runtime.
C/C++ are unmanaged languages where the developer is responsible for memory management and security considerations. In contrast, managed code (C#, F# and Visual Basic to name a few) can be run on top of .NET. When you write and compile code in these high-level languages you get Intermediate Language code which the runtime then compiles and executes.
Using C# as an example hereon, each time a new object is created the common language runtime allocates memory for the object from the managed heap. The runtime continues to allocate space for new objects as long as their is address space available in the managed heap.
Considering memory is not infinite, at some point the GC must free up some memory. The optimization engine determines the best time to perform a collection, based upon the allocations being made. When the GC performs a collection to reclaim memory it checks for objects in the managed heap that are no longer being used.
Running processes have their own virtual address space while multiple processes on the same machine share the same physical memory. Processes running on 32-bit computers have 2-GB user-mode virtual address space. The garbage collector allocates and frees virtual memory for you on the managed heap.
When you initialize a new process, the runtime reserves a contiguous region of address space for the process which is referred to as the managed heap. The managed heap maintains a pointer to the address where the next object in the heap will be allocated. All reference types are allocated on the managed heap.
The GCs optimizing engine determines the best time to perform a collection based on the allocations being made. When the GC performs a collection it determines which objects are no longer being used by examining the applications roots.
An application’s roots include static fields, local variables on a thread’s stack, CPU registers, GC handles, and the finalize queue.
Garbage Collection only occurrs when one of the following conditions is true:
GC.Collect
method is called, this is uncommon and mostly for unique
situations/ testing.Before a garbage collection starts, all managed threads are suspended except for the thread that triggered the garbage collection.
GC provides the following benefits:
In 1984 David Ungar came up with a generational hypothesis which gave birth to the generational garbage collectors.
The GC algorithm is based on several considerations:
Garbage collection primarily occurs with the reclamation of short-lived objects. The managed heap is divided into three generations to optimize the performance of the garbage collector. Generations 0, 1, and 2, so it can handle long-lived and short-lived objects separately.
The garbage collector stores new objects in generation 0. Generation 1 and 2 store objects created early in the application’s lifetime that survive collections (and thus promoted, more details on this to follow).
The reason for this is that it is more performant to compact a portion of the managed heap than the entire heap, thus releasing the memory in a specific generation rather than release the memory for the entire managed heap each time it performs a collection.
Objects that are not reclaimed in a garbage collection are known as survivors and are promoted to the next generation:
A garbage collection has the following phases:
This is just a high-level overview of my knoweldge, the MS Docs provie a great overview of GC if you want to know more.