We use a web farm using .NET. Each web server contains a significant number of static objects in it. Gen 2 (GC) garbage collection takes 10-20 seconds and it starts every 5 minutes. We used more or less the same problems that StackOverflow encountered: http://samsaffron.com/archive/2011/10/28/in-managed-code-we-trust-our-recent-battles-with-the- net-garbage-collector
We are currently reducing the number of objects in the cache. However, this takes time.
At the same time, we implemented the methods described here to receive notifications in .NET about approaching the GC. The goal is to get the web server out of the farm when the GC approaches and include it in the farm after the GC completes. However, we only receive a notification for 0.7% of all GCs. We use maxGenerationThreshold and largeObjectHeapThreshold 8. We tried other thresholds, but the number of skipped GCs did not change.
We use shared server garbage collection ( http://msdn.microsoft.com/en-us/library/ms229357.aspx ). GCLatencyMode is interactive (see http://msdn.microsoft.com/en-us/library/system.runtime.gclatencymode.aspx ). Here we again tried to use other GC modes (workstation mode, package, etc.). Again, we did not receive a notification for most GC.
Are we doing something wrong, or is it impossible to get a notification for each GC? How can we increase the number of notifications?
http://assets.red-gate.com/community/books/assets/Under_the_Hood_of_.NET_Management.pdf, GC , Gen2 ~ 10 . , , , , , , , . ?
, :
GC.RegisterForFullGCNotification(gcThreshold, gcThreshold);
thWaitForFullGC = new Thread(WaitForFullGCProc);
thWaitForFullGC.Name = "HealthTestGCNotificationListenerThread (Threshold=" + gcThreshold + ")";
thWaitForFullGC.IsBackground = true;
WaitForFullGCProc():
private void WaitForFullGCProc()
{
try
{
while (!gcAbort)
{
GCNotificationStatus s;
do
{
int timeOut = CheckForMissedGc() > 0 ? 5000 : (10 * 60 * 1000);
s = GC.WaitForFullGCApproach(timeOut);
if (this.GcState == GCState.InducedUnnotified)
{
this.GcState = GCState.Okay;
}
} while (s == GCNotificationStatus.Timeout);
if (s == GCNotificationStatus.Succeeded)
{
SetGcState(GCState.Approaching, "GC is approaching..");
gcApproachNotificationCount++;
}
else
{
...
}
Stopwatch stopwatch = Stopwatch.StartNew();
s = GC.WaitForFullGCComplete((int)PrewarnTime.TotalMilliseconds);
long elapsed = stopwatch.ElapsedMilliseconds;
if (s == GCNotificationStatus.Timeout)
{
if (this.ForceGCWhenApproaching && !this.IsInGc && !this.IsPeriodicGcApproaching)
{
this.IsInGc = true;
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, blocking: true);
GC.WaitForPendingFinalizers();
elapsed = stopwatch.ElapsedMilliseconds;
this.IsInGc = false;
}
}
}
gcAbort = false;
}
catch (Exception e)
{
}
}