简体   繁体   English

GC启动和停止事件

[英]GC start and stop events

Isn't it possible to get an event when the GC begins? GC启动时是否有可能获得事件? I want to time each individual GC so I can see if pauses in my server are due to GC or something else. 我想为每个GC计时,以便我可以看到我的服务器中的暂停是由于GC还是其他原因。

The GC pauses all .NET threads while running, right? GC在运行时暂停所有.NET线程,对吗? (Except the thread that it runs on, of course). (当然,除了它运行的线程)。 How about unmanaged threads? 非托管线程怎么样?

Thanks! 谢谢!

There's a much easier way if all you want to do is figure out when GC is running, it won't tell you exactly when it starts, nor at all when it ends, but if you can see the output from this method I'll describe here when you notice the pauses on your servers, you should be able to figure out if GC is your problem. 有一个更容易的方法,如果您想要做的就是在GC运行时弄清楚,它不会准确地告诉您何时开始,也不会告诉它何时结束,但是如果您可以看到此方法的输出我将会在此处描述当您注意到服务器上的暂停时,您应该能够确定GC是否是您的问题。

Basically, what you do is create a class with a finalizer, construct an object of that class and just drop the reference (ie. don't store it). 基本上,你要做的是创建一个带有终结器的类,构造该类的对象,然后删除引用(即不存储它)。 The object will then be left until GC hits it, where it will be finalized. 然后该对象将被保留,直到GC命中它,它将在那里完成。

The trick now is in the finalizer you log (in whatever way you want to use) that the finalizer has run, and unless the appdomain is in the process of shutting down, you simply construct a new object which you promptly drop the reference to, ready for the next GC. 现在的诀窍是你在终结器中记录终结器(以任何你想要的方式使用),除非appdomain正在关闭,你只需构造一个新的对象,你迅速删除引用,准备下一个GC。

This works surprisingly well and doesn't need much work from your part. 这非常有效,并且您不需要做太多工作。

Here's the class I use: 这是我使用的课程:

namespace PresentationMode
{
    /// <summary>
    /// This class is used to get a running log of the number of garbage collections that occur,
    /// when running with logging.
    /// </summary>
    public sealed class GCLog
    {
        #region Construction & Destruction

        /// <summary>
        /// Releases unmanaged resources and performs other cleanup operations before the
        /// <see cref="GCLog"/> is reclaimed by garbage collection.
        /// </summary>
        ~GCLog()
        {
            SiAuto.Main.LogMessage("GARBAGE COLLECTED");
            if (!AppDomain.CurrentDomain.IsFinalizingForUnload() && !Environment.HasShutdownStarted)
                new GCLog();
        }

        #endregion

        #region Public Static Methods

        /// <summary>
        /// Registers this instance.
        /// </summary>
        public static void Register()
        {
#if DEBUG
            if (SiAuto.Si.Enabled)
                new GCLog();
#endif
        }

        #endregion
    }
}

All you have to do is call the .Register() method. 您所要做的就是调用.Register()方法。 Note here that I use SmartInspect as my logging tool so you want to replace the calls involving SiAuto with something else. 请注意,我使用SmartInspect作为我的日志记录工具,因此您希望将涉及SiAuto的调用替换为其他内容。

In another project, also using SmartInspect , which has the notion of 'watches', where you can send numeric values, and graph them in the logging tool, I sent the values 0, 1, and then 0 in rapid succession, as this would give me a graph that held at 0 at all times, but produced a sharp spike whenever there was a GC running. 在另一个项目中,也使用具有“手表”概念的SmartInspect ,您可以在其中发送数值,并在记录工具中绘制图形,我快速连续发送值0,1和0,因为这样给我一个始终保持在0的图形,但是当GC运行时会产生尖锐的尖峰。 Couple this with a background thread that monitored CPU usage and memory used gave me very good data to work with. 将此与监视CPU使用率和使用的内存的后台线程相结合,为我提供了非常好的数据。

This is what the Profiling API is for. 这就是Profiling API的用途。 See ICorProfilerCallback2::GarbageCollectionStarted and GarbageCollectionFinished . 请参阅ICorProfilerCallback2 :: GarbageCollectionStartedGarbageCollectionFinished

As this is a profiler, it obviously isn't suitable for routine use on a production system. 由于这是一个分析器,它显然不适合生产系统的常规使用。 But it sounds like you're primarily interested in this for diagnostic purposes anyway. 但听起来你对这个主要感兴趣的是用于诊断目的。 So it might be worth checking whether one of the commercial profilers offers this facility already, or whether the perfmon counters would suffice -- writing your own profiler could be an awfully heavyweight solution! 所以可能值得检查其中一个商业剖析器是否已经提供此设施,或者perfmon计数器是否足够 - 编写自己的剖析器可能是一个非常重量级的解决方案!

GC不会发出任何事件,但您可以使用计时器并调用GC.CollectionCount()来查看集合何时发生。

.net 4具有可能对您有用的垃圾收集事件

unmanaged threads are not affected by the GC. 非托管线程不受GC影响。

You can see the GC performance in the performance monitor, here is an article on how to create a system monitor. 您可以在性能监视器中查看GC性能,以下是有关如何创建系统监视器的文章。 I think you can get a counter to the GC somehow. 我想你可以以某种方式得到GC的反击。

Codeproject CodeProject上

Here is a description of the perf counters used by the GC 以下是GC使用的perf计数器的说明

GC counters GC计数器

GC性能计数器中的%Time应该为您提供所需的数据。

You can accuratly monitor and measure GC suspensions using CLR Hosting . 您可以使用CLR Hosting准确地监视和测量GC暂停。 You can find an example for exactly that in this post: Accurately Measuring GC Suspensions . 您可以在这篇文章中找到一个完全相同的例子: 准确测量GC悬浮液

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM