Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GC start and stop events

Isn't it possible to get an event when the GC begins? I want to time each individual GC so I can see if pauses in my server are due to GC or something else.

The GC pauses all .NET threads while running, right? (Except the thread that it runs on, of course). How about unmanaged threads?

Thanks!

like image 435
Rabbit Avatar asked Oct 08 '09 06:10

Rabbit


People also ask

Does GC stop all threads?

Although the Parallel GC uses multiple threads for garbage collection, it still pauses all application threads while running.

When should I run GC collect?

Call GC. Collect() before it goes idle. Reason: If a process is idle, the garbage collector will not kick in, thus unused memory will be not released during idle time.

How does C# garbage collection work?

How GC works? GC works on managed heap, which is nothing but a block of memory to store objects, when garbage collection process is put in motion, it checks for dead objects and the objects which are no longer used, then it compacts the space of live object and tries to free more memory.


2 Answers

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.

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.

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.

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. Note here that I use SmartInspect as my logging tool so you want to replace the calls involving SiAuto with something else.

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. Couple this with a background thread that monitored CPU usage and memory used gave me very good data to work with.

like image 179
Lasse V. Karlsen Avatar answered Sep 29 '22 13:09

Lasse V. Karlsen


This is what the Profiling API is for. See ICorProfilerCallback2::GarbageCollectionStarted and GarbageCollectionFinished.

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!

like image 35
itowlson Avatar answered Sep 29 '22 13:09

itowlson