As you may know, there are different GC modes to choose from depending on the type of application you’re using: Server GC, Workstation GC, and Concurrent GC (more info). These settings are process-wide, set at the beginning of the process. Once the GC mode is set, it cannot be changed. In Orcas, we’ve added the concept of GC Latency Modes that while process-wide, can be changed during the lifetime of the process to meet an application’s needs.The Latency Modes can be accessed as new properties onto the GCSettings class:
System.Runtime.GCLatencyMode System.Runtime.GCSettings.LatencyMode { get; set; }
The values for GCLatencyMode are Batch, Interactive and LowLatency.
How does LowLatency mode work?
When you set the latency mode to LowLatency, the GC will perform almost no generation 2 collections, nor will it start any new concurrent collections. Since generation 2 is unbounded and can become very large, collecting it can cause your managed threads to pause for short amounts of time. This can be unacceptable for certain scenarios.
To be clear, I’m not talking about real-time application requirements, rather requirements that a short-running block of code run smoothly with minimal interruptions from the runtime. LowLatency mode is not real-time mode.
I mentioned above that in LowLatency mode, the GC will perform almost no most generation 2 collections, but there are situations when it will. As we know, there are three things that cause the GC to perform a collection (more info):
How to safely use LowLatency mode
As you might have guessed, since generation 2 is rarely collected, OutOfMemoryExceptions are more likely under LowLatency mode. Here are some guidelines to follow to avoid potential problems:
Here’s a code sample of how to use LowLatency mode
// preallocate objects hereGCLatencyMode oldMode = GCSettings.LatencyMode;RuntimeHelpers.PrepareConstrainedRegions();try{ GCSettings.LatencyMode = GCLatencyMode.LowLatency; // perform time-sensitive actions here /* minimize: -all allocations, especially LOH allocations -pinning -allocations on other threads */}catch (ApplicationException){ // catch any exceptions you expect your application to throw // perform cleanup code}finally{ // always set the mode back! GCSettings.LatencyMode = oldMode; }
// preallocate objects hereGCLatencyMode oldMode = GCSettings.LatencyMode;RuntimeHelpers.PrepareConstrainedRegions();try{ GCSettings.LatencyMode = GCLatencyMode.LowLatency;
// perform time-sensitive actions here
/* minimize: -all allocations, especially LOH allocations -pinning -allocations on other threads */}catch (ApplicationException){ // catch any exceptions you expect your application to throw // perform cleanup code}finally{ // always set the mode back! GCSettings.LatencyMode = oldMode; }
Remember, this mode can cause failures in your application, so please use good judgment when using it.