Skip to content

Instantly share code, notes, and snippets.

View Criteo-dotnet-blog's full-sized avatar

Criteo-dotnet-blog

View GitHub Profile
public sealed class ContentionTraceData : TraceEvent
{
public ContentionFlags ContentionFlags { get; }
private void OnGCFinalizeObject(FinalizeObjectTraceData data)
{
if (data.ProcessID != _processId)
return;
// the type id should have been associated to a name via a previous TypeBulkType event
NotifyFinalize(data.TimeStamp, data.ProcessID, data.TypeID, _types[data.TypeID]);
}
private void OnTypeBulkType(GCBulkTypeTraceData data)
{
if (data.ProcessID != _processId)
return;
// keep track of the id/name type associations
for (int currentType = 0; currentType < data.Count; currentType++)
{
GCBulkTypeValues value = data.Values(currentType);
_types[value.TypeID] = value.TypeName;
public override IEnumerable<(ulong objAddress, ClrType clrType, ulong size)> EnumerateObjectDetails()
{
ClrHeap heap = _segments[0].Heap;
Dictionary<ulong, ClrType> typeCache = new Dictionary<ulong, ClrType>(32768);
for (int iSegment = 0; iSegment < _segments.Length; ++iSegment)
{
ClrSegment segment = _segments[iSegment];
// unlike the default implementation, we are trying to avoid
private static IEnumerable<(ulong ObjAddress, ClrType clrType, ulong size)> EnumerateTypeInstances(ClrHeap heap)
{
foreach (ulong objAddress in heap.EnumerateObjectAddresses())
{
ClrType type = heap.GetObjectType(objAddress);
ulong size = type.GetSize(objAddress);
yield return (objAddress, type, size);
}
}
private static void OnExceptionStart(ExceptionTraceData data)
{
Console.WriteLine($"{data.EventName} --> {data.ExceptionType} : {data.ExceptionMessage}");
}
// listen to all CLR events
userSession.Source.Clr.All += delegate (TraceEvent data)
{
// skip verbose and unneeded events
if (SkipEvent(data))
return;
// raw dump of the events
Console.WriteLine($"{data.ProcessID,7} <{data.ProviderName}:{data.ID}>__[{data.OpcodeName}] {data.EventName} <| {data.GetType().Name}");
};
// register handlers for events on the session source
// more on this later...
// decide which provider to listen to with filters if needed
userSession.EnableProvider(
ClrTraceEventParser.ProviderGuid,
TraceEventLevel.Verbose,
(ulong)(
ClrTraceEventParser.Keywords.Contention | // thread contention timing
ClrTraceEventParser.Keywords.Threading | // threadpool events
string sessionName = "EtwSessionForCLR_" + Guid.NewGuid().ToString();
Console.WriteLine($"Starting {sessionName}...\r\n");
using (TraceEventSession userSession = new TraceEventSession(sessionName, TraceEventSessionOptions.Create))
{
Task.Run(() =>
{
// register handlers for events on the session source
// more on this later...
// decide which provider to listen to with filters if needed
Console.WriteLine("Current ETW sessions:");
foreach(var session in TraceEventSession.GetActiveSessionNames())
{
Console.WriteLine(session);
}
Console.WriteLine("--------------------------------------------");