gpt4 book ai didi

c# - 错过的垃圾收集通知

转载 作者:行者123 更新时间:2023-12-04 20:47:34 24 4
gpt4 key购买 nike

我们正在使用 .NET 运行一个网络农场。每个 Web 服务器的内存中都保存着大量的静态对象。第 2 代垃圾收集 (GC) 需要 10-20 秒,并且每 5 分钟运行一次。
我们或多或少遇到了 StackOverflow 遇到的相同问题:http://samsaffron.com/archive/2011/10/28/in-managed-code-we-trust-our-recent-battles-with-the-net-garbage-collector

目前,我们正在减少缓存中的对象数量。然而,这需要时间。

同时,我们实现了文档中的方法here在 .NET 中获取有关接近 GC 的通知。
目标是在 GC 临近时将 Web 服务器从场中取出,并在 GC 结束后将其包含到场中。
但是,我们只收到所有 GC 的 0.7% 的通知。
我们使用的 maxGenerationThreshold 和 largeObjectHeapThreshold 为 8。我们尝试了其他阈值,但未命中 GC 的数量没有改变。

我们正在使用并发服务器垃圾收集 ( http://msdn.microsoft.com/en-us/library/ms229357.aspx )。 GCLatencyMode 是交互式的(请参阅 http://msdn.microsoft.com/en-us/library/system.runtime.gclatencymode.aspx )。在这里,我们再次尝试使用其他 GC 模式(工作站模式、批处理等)。同样,我们没有收到大多数 GC 的通知。

是我们做错了什么,还是不可能在每次 GC 发生时都收到通知?
我们如何增加通知的数量?

根据 http://assets.red-gate.com/community/books/assets/Under_the_Hood_of_.NET_Management.pdf , 开始时,当 Gen2 达到 ~10 MB 时触发 GC。我们有很多 RAM,因此如果我们可以手动将此阈值设置为更高级别,则需要更多时间才能达到此阈值,而且在我看来,收到通知的概率会增加。有没有办法修改这个阈值?

这是注册和监听通知的代码:

GC.RegisterForFullGCNotification(gcThreshold, gcThreshold);
// Start a thread using WaitForFullGCProc.
thWaitForFullGC = new Thread(WaitForFullGCProc);
thWaitForFullGC.Name = "HealthTestGCNotificationListenerThread (Threshold=" + gcThreshold + ")";
thWaitForFullGC.IsBackground = true;

WaitForFullGCProc():
    private 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)
{
}
}

最佳答案

Note: This is more of a comment but includes a large code sample.



您是否考虑过尝试通过其他方式获取 GC 通知? Jeffrey Richter(CLR 通过 C#)解释了一种获取通知的好方法,它使用一个对象并检查它的终结器方法是哪一代。

这是这个类:它使用内部对象,如果提供的生成匹配(例如,请参见 new GenObject(0);)或为下一个更高的生成而复活。

您只需使用 GCNotification.GCDone += GCDoneHandler; 订阅即可
 public static class GCNotification
{
private static Action<Int32> s_gcDone = null; // The event's field
public static event Action<Int32> GCDone
{
add
{
// If there were no registered delegates before, start reporting notifications now
if (s_gcDone == null) { new GenObject(0); new GenObject(1); new GenObject(2); }
s_gcDone += value;
}
remove { s_gcDone -= value; }
}
private sealed class GenObject
{
private Int32 m_generation;
public GenObject(Int32 generation) { m_generation = generation; }
~GenObject()
{ // This is the Finalize method
// If this object is in the generation we want (or higher),
// notify the delegates that a GC just completed
if (GC.GetGeneration(this) >= m_generation)
{
Action<Int32> temp = Volatile.Read(ref s_gcDone);
if (temp != null) temp(m_generation);
}
// Keep reporting notifications if there is at least one delegate registered,
// the AppDomain isn't unloading, and the process isn’t shutting down
if ((s_gcDone != null)
&& !AppDomain.CurrentDomain.IsFinalizingForUnload()
&& !Environment.HasShutdownStarted)
{
// For Gen 0, create a new object; for Gen 2, resurrect the object
// & let the GC call Finalize again the next time Gen 2 is GC'd
if (m_generation == 0) new GenObject(0);
else GC.ReRegisterForFinalize(this);
}
else { /* Let the objects go away */ }
}
}
}

关于c# - 错过的垃圾收集通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14997167/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com