Description
Description
Problem Overview
I'm experiencing difficulties trying to precisely measure the start and end times of .NET garbage collection. I need accurate GC duration measurements, but the events currently available through EventListener don't seem to provide complete information about the GC lifecycle.
Questions
- Is there a more accurate event to represent the start of GC, rather than GCSuspendEEBegin_V1?
- Does the current EventListener API provide sufficient information to accurately measure GC duration?
- Is there a recommended approach to measure the complete GC duration?
Reproduction Steps
Reproduction Code
using System;
using System.Diagnostics.Tracing;
public class GCEventListener : EventListener
{
private long _gcStartTime;
private DateTime _case9SystemTime;
protected override void OnEventSourceCreated(EventSource eventSource)
{
if (eventSource.Name != "Microsoft-Windows-DotNETRuntime")
return;
EnableEvents(eventSource, EventLevel.Informational, (EventKeywords)1);
}
protected override void OnEventWritten(EventWrittenEventArgs eventData)
{
switch (eventData.EventId)
{
case 2: /* GCEnd_V1 */
{
DateTime case2SystemTime = DateTime.Now;
var intervalMs = (case2SystemTime - _case9SystemTime).TotalMilliseconds;
Console.WriteLine($"Time interval between case 2 and case 9: {intervalMs:F2}ms");
var cost = TimeSpan.FromTicks(eventData.TimeStamp.Ticks - _gcStartTime).TotalMilliseconds;
Console.WriteLine($"GC ended, time from suspension to end: {cost:F2}ms");
break;
}
case 9: /* GCSuspendEEBegin_V1 */
{
_case9SystemTime = DateTime.Now;
_gcStartTime = eventData.TimeStamp.Ticks;
break;
}
}
}
}
class Program
{
public class ClassA
{ }
static void Main(string[] args)
{
var gcEventListener = new GCEventListener();
for (int i = 0; i < 10000 * 100; i++)
{
var a = new ClassA();
}
GC.Collect();
Console.WriteLine("Press Enter to exit...");
Console.ReadLine();
}
}
Expected behavior
I'm looking to capture events that identify the complete GC lifecycle, including:
- The event or timestamp when GC truly begins
- The event or timestamp when GC ends
Actual behavior
Looking at the output logs, the time difference between eventData.TimeStamp
values seems to be the actual GC duration, but I'm not sure if there are more accurate events to identify the true start time of GC. Currently, I'm using GCSuspendEEBegin_V1 (case 9), but this might only be part of the GC process rather than the starting point.
Time interval between case 2 and case 9: 18.96ms
GC ended, time from suspension to end: 23.25ms
Time interval between case 2 and case 9: 0.01ms
GC ended, time from suspension to end: 1.38ms
Regression?
No response
Known Workarounds
No response
Configuration
.NET version: 9.0.2
Other information
I've noticed that the timestamps in EventData seem to reflect the actual GC duration more accurately than system time measured using DateTime.Now. How can I correctly utilize these timestamps to precisely measure GC performance?