I've got a weird slowdown in my ASP.NET website that I cannot seem to track down. I'm suspecting that GC might be kicking in and halting my threads. To know for sure it would be nice to log every time when GC does occur.
I could make a dummy object and do the logging in its finalizer, but that would then be a one-shot solution, while in my case there are several such inexplainable pauses.
Any ideas?
Added: The environment is VS2008/.NET 3.5 SP1. And no, the Garbage Collection Notifications won't do because they are a method of polling, and don't work for a concurrent GC.
Here's a simple trick. It might not be 100% accurate, but it will probably be good enough.
If you can live with being notified of finalization, then there is a simple method you can use.
Create an object, and don't keep a reference to it. When the object is finalized, you raise your event, and then construct another object. You don't keep a reference to this object either, but it will live until the next time a complete enough collection is performed.
Here's such an object:
public class GCNotifier
{
public static event EventHandler GarbageCollected;
~GCNotifier()
{
if (Environment.HasShutdownStarted)
return;
if (AppDomain.CurrentDomain.IsFinalizingForUnload())
return;
new GCNotifier();
if (GarbageCollected != null)
GarbageCollected(null, EventArgs.Empty);
}
public void Start()
{
new GCNotifier();
}
}
If you want, you can add support for stopping it by having a static boolean field which prevents it from restarting itself upon next finalization.
Hope this is of some help.
Perhpas this article (Garbage Collection Notifications) will help.
you can be notified that a full garbage collection is approaching
The simple answer is "No there are not GC 'events' only the GCNotification function". However you create a wrapper class that will listen to GCNotification
and that wrapper can fire events, but there is no simple event solution like you are looking for.
The reason for this is an event may or may not be processed before the GC completes. So what they have you do instead is spawn a child thread, sleep on WaitForFullGCApproach
or pole if you are not looking for a Full GC, and do your whatever you need to do before the GC happens.
Do you monitor perf-mon? You can watch CPU - overall and by process, .NET memory, including size of each of the generations and counts of the types of GC's. You can also let perf-mon run and log for extended periods of time to look at trends. I find this to be much more useful than discrete 'it's happening right now!' events.
You might want to read this article on ASP.NET Performance Monitoring, and When to Alert Administrators
It includes a section on the GCcounters to look at and what the values mean. For example
% Time in GC. The percentage of time
spent performing the last garbage
collection. An average value of 5% or
less would be considered healthy, but
spikes larger than this are not
uncommon. Note that all threads are
suspended during a garbage collection.
You might also want to take a look a the blog If broken it is, fix it you should It has a number of case studies that go step by step on how to identify a specific problem. For example ASP.NET Case Study: High CPU in GC - Large objects and high allocation rates