Overview
The .NET Framework garbage collector (GC) automatically manages memory allocation and release for managed objects. It provides a robust, high‑performance, and low‑latency environment that helps developers write reliable applications without manual memory management.
How It Works
GC operates on the principle of generational collection. Objects are allocated in Generation 0, promoted to Generation 1 and then to Generation 2 if they survive collections. The collector periodically scans these generations, reclaiming memory from objects that are no longer reachable.
public class Example
{
private static List<byte[]> buffers = new List<byte[]>();
public static void Allocate()
{
// Each allocation goes to Gen 0
buffers.Add(new byte[1024 * 1024]); // 1Â MB
}
}
Configuring GC
GC behavior can be tuned via the runtime
configuration section in app.config
or web.config
.
<configuration>
<runtime>
<gcServer enabled="true" />
<gcConcurrent enabled="false" />
<gcHeapCount value="4" />
</runtime>
</configuration>
For a quick reference see the Configuration Guide.
GC Modes
- Workstation GC – Optimized for client apps; background GC enabled by default.
- Server GC – Optimized for multi‑core servers; creates a heap per logical processor.
- Concurrent (Background) GC – Reduces pause times by performing collection on a separate thread.
- Non‑Concurrent GC – Full blocks while the GC runs; useful for short‑lived processes.
Best Practices
- Prefer using
using
statements orDispose
patterns for unmanaged resources. - Avoid large object allocations on the LOH when possible; reuse buffers.
- Do not call
GC.Collect()
in production code unless you have a proven scenario. - Profile memory usage with tools like dotMemory, PerfView, or Visual Studio Diagnostic Tools.
Code Examples
Forcing a Generation 0 Collection (Not Recommended)
GC.Collect(0, GCCollectionMode.Forced, blocking: true, compacting: true);
Inspecting GC Information
Console.WriteLine($"Total memory: {GC.GetTotalMemory(false)} bytes");
Console.WriteLine($"Gen 0 collections: {GC.CollectionCount(0)}");
Console.WriteLine($"Gen 1 collections: {GC.CollectionCount(1)}");
Console.WriteLine($"Gen 2 collections: {GC.CollectionCount(2)}");