.NET Core Runtime Documentation

Garbage Collection

Understanding Garbage Collection in .NET Core

Garbage Collection (GC) is an automatic memory management process in the .NET Core runtime. Its primary responsibility is to reclaim memory that is no longer being used by an application, preventing memory leaks and improving overall application stability and performance.

The .NET GC is a generational, compacting garbage collector. This means it categorizes objects into generations based on their lifespan and periodically moves objects to reduce fragmentation and improve allocation speed.

Generations

The .NET GC uses a generational approach, dividing the managed heap into three generations:

When a GC cycle occurs, it starts with the youngest generation (Gen 0). If the heap is still under memory pressure after collecting Gen 0, it proceeds to Gen 1, and then to Gen 2. This strategy is efficient because most objects are short-lived and can be collected quickly in Gen 0.

Compacting GC

The .NET GC is also a compacting collector. After identifying and reclaiming unreachable objects, the GC moves the remaining, reachable objects closer together in memory. This process:

Note: Compaction is a performance-intensive operation and is primarily performed on Gen 0 and Gen 1. Gen 2 may or may not be compacted depending on the GC mode and pressure.

GC Modes

.NET Core supports different GC modes, which can be configured to optimize for various application scenarios:

You can configure the GC mode using the runtimeconfig.json file or environment variables.


// Example runtimeconfig.json snippet
{
  "runtimeOptions": {
    "configProperties": {
      "System.GC.Mode": "Server" // or "Workstation"
    }
  }
}
            

Manual GC Control

While the GC is automatic, developers have some limited ability to influence its behavior. The most common way is by explicitly triggering a garbage collection using GC.Collect().

However, it is generally not recommended to call GC.Collect() unless you have a very specific reason, such as managing unmanaged resources explicitly or for testing scenarios. Relying on the automatic GC is usually more efficient and less error-prone.


using System;

public class Example
{
    public static void Main(string[] args)
    {
        // ... perform some operations ...

        // Explicitly trigger a full, blocking garbage collection.
        // Use with caution!
        // GC.Collect();
        // GC.WaitForPendingFinalizers(); // Often called after GC.Collect()
    }
}
            

The GC.WaitForPendingFinalizers() method waits for any finalizers (destructors) to complete. This is often paired with GC.Collect().

Performance Considerations

To optimize GC performance in your .NET Core applications: