Course contentsShow
← C#
Lesson 1773 of 1,90816. Performance and DiagnosticsFree lesson

Managing Large-Scale Memory Pressure via GC.Collect

Students will evaluate the rare cases where manual collection intervention is appropriate.

In this lesson, you will learn why invoking GC.Collect() is almost always an anti-pattern and the extremely narrow set of scenarios where it serves as a legitimate tool for managing memory pressure.

The Problem with Manual Intervention

For 99.9% of .NET applications, calling GC.Collect() is counterproductive. The Garbage Collector (GC) is a highly sophisticated engine that dynamically tunes its behavior based on heap allocation rates and CPU load. By manually forcing a collection, you stop the world (suspending your application threads), interrupt the GC’s internal heuristics, and often trigger a "Full GC" (Generation 2), which is the most expensive type of collection.

When is it Appropriate?

There is one specific scenario where manual collection makes sense: Predictable, low-frequency, large-scale cleanup.

Consider an application that performs occasional, massive batch imports—for example, processing a 5GB XML file that creates millions of short-lived objects. If you let the GC handle this naturally, it may trigger collections while your CPU is already saturated, potentially causing latency spikes during critical business operations.

If you know for a fact that the massive object graph has just gone out of scope, calling GC.Collect(2, GCCollectionMode.Optimized, true, true) can be a surgical strike:

public void ProcessMassiveBatch()
{
    // ... logic that allocates millions of short-lived objects ...
    
    // Explicitly cleanup after the massive, infrequent task is finished
    // to reclaim memory before the next idle period.
    GC.Collect(2, GCCollectionMode.Optimized, blocking: true, compacting: true);
}

The Trade-offs

When you call GC.Collect, you must consider the "Blocking" and "Compacting" parameters. Setting blocking: true forces the application to wait until the collection completes. While this prevents the GC from running in the background while you are trying to do other work, it creates a massive pause in your P99 latency metrics.

Before reaching for GC.Collect(), always ensure you have analyzed your application using DotTrace or EventCounters to prove that the automatic GC heuristics are actually failing your specific workload requirements.

Key Takeaway: Only invoke GC.Collect() as a last resort for infrequent, high-volume batch operations where you want to reclaim memory during a known, non-critical window to prevent non-deterministic pauses later.