Net Garbage Collection: How Managed Memory Works
- Average speed
- km/h
- Result
- Finish time
- 50 min
- You entered
- Distance
- 10 km
- You entered
Net garbage collection (GC) is the automatic memory management system in .NET that frees developers from manually deallocating objects, preventing memory leaks and dangling pointers. It works by tracking object references, identifying unreachable objects, and reclaiming their memory in generations, with tuning options like workstation/server modes, latency levels, and GC settings to balance throughput, latency, and memory usage.
Formula
The calculator above computes your average pace and speed for a run or ride. The formulas are:
- Pace (min/km) = Finish time (minutes) / Distance (km)
- Speed (km/h) = Distance (km) / (Finish time (minutes) / 60)
Where Finish time is in minutes, Distance is in kilometers, Pace is in minutes per kilometer, and Speed is in kilometers per hour.
Worked Example
Suppose you finish a 10 km run in 50 minutes. Using the default values:
- Pace = 50 min / 10 km = 5.00 min/km
- Speed = 10 km / (50 min / 60) = 10 / 0.8333 = 12.00 km/h
The calculator shows a pace of 5.00 min/km and a speed of 12.00 km/h.
Why Garbage Collection Matters
In languages like C and C++, developers manually allocate and free memory. This leads to two classic bugs: memory leaks (forgetting to free) and dangling pointers (freeing too early). .NET’s GC eliminates both by automatically reclaiming memory that is no longer reachable from the application’s roots (static fields, local variables, CPU registers, and GC handles). This makes development safer and more productive, but it comes with a cost: the GC pauses your application threads to collect garbage, and tuning is often needed for performance-critical applications.
How the .NET GC Works
The .NET GC is a generational, mark-and-compact collector. It divides managed heap objects into three generations:
- Gen 0: Short-lived objects (e.g., temporary variables). Collected most frequently.
- Gen 1: Objects that survive a Gen 0 collection.
- Gen 2: Long-lived objects (e.g., static data, large caches). Collected rarely.
When a collection occurs, the GC marks all reachable objects by following references from roots, then compacts (moves) surviving objects to reduce fragmentation. Objects that survive multiple collections are promoted to the next generation. The GC also uses a separate Large Object Heap (LOH) for objects ≥ 85,000 bytes, which is not compacted by default to avoid performance costs.
GC Modes and Latency Levels
.NET offers two main GC flavors:
- Workstation GC: Default for client apps. Optimized for low latency and responsiveness. Can be concurrent (background) or non-concurrent.
- Server GC: Default for server apps (ASP.NET Core). Creates one GC heap per logical CPU, enabling parallel collections that scale with cores. Higher throughput but more memory usage and potentially longer pauses.
You can also set latency levels via GCSettings.LatencyMode: Batch (max throughput, long pauses), Interactive (default, balanced), LowLatency (minimize pauses, but increases memory footprint and Gen 2 collections), and SustainedLowLatency (for background GC, avoids blocking Gen 2). Choose based on whether you need responsiveness or raw throughput.
How to Tune .NET Garbage Collection
Tuning GC involves adjusting runtime settings via project files, environment variables, or runtimeconfig.json. Common knobs:
- Server GC: Set
<ServerGarbageCollection>true</ServerGarbageCollection>in your .csproj or useDOTNET_gcServer=1. - Concurrent GC:
<ConcurrentGarbageCollection>false</ConcurrentGarbageCollection>to disable background GC (rarely needed). - Latency mode: Set via
System.Runtime.GCSettings.LatencyModein code. - Heap count:
DOTNET_gcHeapCountto limit heaps for server GC. - LOH compaction:
DOTNET_gcServerandGCSettings.LargeObjectHeapCompactionModeto force compaction after a Gen 2 collection.
Start by measuring your app’s GC statistics with performance counters (e.g., % Time in GC, Gen 0/1/2 Collections). If you see high pause times, try LowLatency for interactive apps; if you see excessive memory, consider server GC or reducing object allocations. Always test with realistic workloads, as GC tuning is highly workload-dependent.
Common Problems and Misconceptions
One common misconception is that GC prevents all memory leaks. In reality, you can still leak memory by holding references to objects longer than needed (e.g., event handlers, static collections). Another issue is fragmentation, especially on the LOH, which can cause OutOfMemoryException even with free memory. Also, calling GC.Collect() manually is usually discouraged because it disrupts the GC’s self-tuning; let the runtime decide.
Comparing .NET GC with Other Runtimes
Java’s G1 and ZGC, Go’s non-generational concurrent GC, and Python’s reference counting with cyclic GC each have different trade-offs. .NET’s GC is generational and compacting, which reduces fragmentation but can cause pause times. Java offers more tunable pause-time goals, while Go prioritizes low latency but may use more memory. Python’s reference counting is immediate but requires cycle detection. Understanding these differences helps you choose the right platform for latency-sensitive or memory-constrained applications.
Costs and Safety Considerations
GC adds CPU overhead for marking and compacting, and pause times can affect real-time systems. However, it eliminates entire classes of bugs, improving safety and developer productivity. For safety-critical applications, you can use GC.TryStartNoGCRegion to temporarily suppress GC during critical sections, but this requires careful planning to avoid running out of memory. Always test under load to ensure your tuning does not cause unexpected OutOfMemory exceptions.
Alternatives to Automatic GC
If you need deterministic memory management, you can use Span<T> and Memory<T> for stack-allocated or pooled buffers, or manually manage unmanaged memory via Marshal.AllocHGlobal and IDisposable. For high-performance scenarios, object pooling (e.g., ArrayPool<T>) reduces GC pressure by reusing objects. These alternatives give you control but require discipline to avoid leaks.
Frequently Asked Questions
What is the difference between workstation and server GC?
Workstation GC is optimized for client apps with one heap and lower memory usage, while server GC creates a heap per core and uses parallel collections for higher throughput. Server GC is ideal for multi-threaded server workloads but uses more memory and can have longer pauses.
Why does my .NET app use so much memory?
High memory usage can be due to large object allocations, excessive Gen 2 collections, or holding references to objects longer than needed. Use performance counters to see GC heap sizes and allocation rates, and profile your code to find unnecessary allocations.
Should I call GC.Collect() manually?
Generally no. The GC self-tunes based on allocation patterns and memory pressure. Manual calls can hurt performance by forcing collections at inopportune times. Only use it in rare cases like testing or when you need to measure memory usage.
How do I reduce GC pause times?
Use LowLatency or SustainedLowLatency mode for interactive apps, enable server GC for multi-core servers, and minimize allocations by reusing buffers and avoiding LINQ in hot paths. Also consider using ArrayPool for large arrays.
What is the Large Object Heap and why is it special?
The LOH holds objects ≥ 85,000 bytes. It is not compacted by default to avoid moving large blocks, which can cause fragmentation. You can force compaction after a Gen 2 collection via GCSettings.LargeObjectHeapCompactionMode.
Can I disable garbage collection in .NET?
No, but you can suppress it temporarily with GC.TryStartNoGCRegion for critical sections. This is risky and should be used sparingly, as it can lead to OutOfMemoryException if you allocate too much during the suppressed period.
Related
Formula used
in t | Finish time | min | 50 | 0 in d | Distance | km | 10 | 0 out pace | Average pace | min/km | t / d | 2 out speed | Average speed | km/h | d / (t / 60) | 2
Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.