.NET kullanarak bir web grubu çalıştırıyoruz. Her web sunucusu, hafızasında önemli miktarda statik nesne barındırır. Gen 2 çöp toplama (GC) 10-20 saniye sürüyor ve her 5 dakikada bir çalışıyor. StackOverflow'un çalıştırdığı aynı sorunlara daha fazla veya daha az rastladık: http://samsaffron.com/archive/2011/10/28/in-managed-code-we-trust-our-recent-battles-with-the-net-garbage-collectorÖzürlü Çöp Toplama Bildirimleri
Şu anda önbellekteki nesne sayısını azaltıyoruz. Ancak, bu zaman alır.
Aynı zamanda, .NET'te GC'lere yaklaşma konusunda bildirim almak için here belgelenen yöntemleri uyguladık. Amaç, bir GC yaklaştığında bir web sunucusunu çiftlik dışına çıkarmak ve GC bittikten sonra çiftliğe dahil etmektir. Ancak, yalnızca tüm GC'lerin% 0.7'si için bir bildirim alıyoruz. Biz bir maxGenerationThreshold ve 8 büyükObjectHeapThreshold kullanıyoruz. Diğer eşikleri denedik ama cevapsız GC'ler değişmedi.
Eşzamanlı sunucu çöp toplama (http://msdn.microsoft.com/en-us/library/ms229357.aspx) kullanıyoruz. GCLatencyMode, Etkileşimli (bkz. http://msdn.microsoft.com/en-us/library/system.runtime.gclatencymode.aspx). Burada yine diğer GC modlarını kullanmaya çalıştık (İş İstasyonu modu, Parti vb.). Ve yine çoğu GC'ler için bir bildirim almadık.
Yanlış bir şey mi yapıyoruz, yoksa gerçekleşen her GC için bildirim almak imkansız mı? Bildirimlerin sayısını nasıl artırabiliriz?
http://assets.red-gate.com/community/books/assets/Under_the_Hood_of_.NET_Management.pdf'a göre, başlangıçta Gen2 ~ 10 MB isabet ettiğinde bir GC tetiklenir. Çok fazla RAM'imiz var, bu yüzden bu eşiği daha yüksek bir seviyeye ayarlayabilirsek, bu eşiğe ulaşmak daha fazla zaman alacaktır ve benim anlayışımda olasılık bir bildirim almak için artacaktır. Bu eşiği değiştirmenin bir yolu var mı?
GC.RegisterForFullGCNotification(gcThreshold, gcThreshold);
// Start a thread using WaitForFullGCProc.
thWaitForFullGC = new Thread(WaitForFullGCProc);
thWaitForFullGC.Name = "HealthTestGCNotificationListenerThread (Threshold=" + gcThreshold + ")";
thWaitForFullGC.IsBackground = true;
WaitForFullGCProc():
Bu
bildirimleri kaydeder ve dinler koduprivate void WaitForFullGCProc()
{
try
{
while (!gcAbort)
{
// Check for a notification of an approaching collection.
GCNotificationStatus s;
do
{
int timeOut = CheckForMissedGc() > 0 ? 5000 : (10 * 60 * 1000);
s = GC.WaitForFullGCApproach(timeOut);
if (this.GcState == GCState.InducedUnnotified)
{
// Set the GcState back to okay to prevent the message from staying in the ApplicationMonitoring.
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)
{
}
}
ile abone? – Alex
'GC.RegisterForFullGCNotification (gcThreshold, gcThreshold); // WaitForFullGCProc kullanarak bir konu başlat. thWaitForFullGC = yeni Thread (WaitForFullGCProc); thWaitForFullGC.Name = "HealthTestGCNotificationListenerThread (Eşik =" + gcThreshold + ")"; thWaitForFullGC.IsBackground = true; – kopernik