Low-Latency GC in .NET 3.5
Join the DZone community and get the full member experience.Join For Free
GC flavors are a static performance optimization for the .NET garbage collector. Under various circumstances, applications can opt-in (before runtime) to a runtime mode that affects the GC’s behavior to better suit the specific application in question. For a succinct yet complete description of GC flavors, Maoni’s blog is a great source of information.
.NET 3.5 (or .NET 2.0 SP1) adds an additional API that can change the GC flavor under some circumstances. It is available as the System.Runtime.GCSettings class, which has two properties: IsServerGC and LatencyMode.
The IsServerGC property is a read-only property that specifies whether the application is running under the server GC. It can't be used to opt into server GC at runtime – it only reflects the state of the application's configuration or the CLR host's GC flavor definition.
The LatencyMode property, on the other hand, takes the values of the GCLatencyMode enumeration, which are: Batch, Interactive and LowLatency. Batch corresponds to server GC (it is the default and the only possible value when server GC is enabled) or to non-concurrent workstation GC; Interactive corresponds to concurrent workstation GC. Note that if the application is running under workstation GC, the LatencyMode property can be used to switch between concurrent and non-concurrent GC at runtime.
The final, most interesting value of the GCLatencyMode enumeration is LowLatency, which is only available when using workstation GC. This value signals to the garbage collector that your code is currently in the middle of a short-term time-sensitive operation where a garbage collection might be harmful. This is not the value of choice if you're about to execute missile-guiding code for reasons to be seen shortly. It is useful, however, if you're in the middle of performing a UI animation, and a garbage collection will be disruptive for the user experience.
The low latency garbage collection mode implied by the LowLatency enumeration value instructs the garbage collector to refrain from performing full collections unless absolutely necessary – e.g., if the operating system is running low on physical memory (the effects of paging could be even worse than the effects of performing a full collection). Low latency does not mean the garbage collector is off – partial collections (of the low generations) will still be performed – but the garbage collector's share of the application's processing time will be significantly lower.
Using the low latency GC mode can be tricky because forgetting to reset it back to the previous value can result in disastrous consequences. Additionally, the amount of time you want to spend with a low latency GC mode must be kept to a minimum – the long-term effects once you exit the low latency mode and the GC aggressively begins to reclaim unused memory can hinder the application's performance. Finally, if you don't have full control of all allocations taking place within your process (e.g. if you're hosting plug-ins or have multiple background threads doing independent work), remember that switching to the low latency GC mode affects the entire process, and can cause undesired effects for other allocation paths.
The only safe way of using the low latency GC mode is within a constrained execution region (CER), because it is the only way of guaranteeing that the latency mode will revert to its previous value. The following code (snipped from Chris Lyon’s blog) demonstrates how this can be accomplished:
GCLatencyMode oldMode = GCSettings.LatencyMode;
GCSettings.LatencyMode = GCLatencyMode.LowLatency;
// perform time-sensitive actions here
GCSettings.LatencyMode = oldMode;
When using the low latency GC mode, it is advisable to force garbage collections at safe points when it is known that the time-sensitive work has idled and can afford pausing to perform a collection. Staying in low latency mode without performing a collection for a long period of time might result in out of memory conditions. Generally speaking, if the application is sensitive to garbage collection timing, it's reasonable to force a collection during idle times to influence a biased redistribution of garbage collection overhead into the idle run time regions.
Published at DZone with permission of Sasha Goldshtein, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.