Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Decoding traces produced by generational aware analysis.
  • Loading branch information
cshung committed Nov 17, 2020
commit 877c4da519231f9e696176e83aa54cef918bebb4
22 changes: 20 additions & 2 deletions src/EtwHeapDump/DotNetHeapDumpGraphReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ internal void SetupCallbacks(MemoryGraph memoryGraph, TraceEventDispatcher sourc
}
};

source.Clr.GCGenAwareStart += delegate (GenAwareBeginTraceData data)
{
m_seenStart = true;
m_ignoreEvents = false;
};

source.Clr.GCStart += delegate (GCStartTraceData data)
{
// If this GC is not part of a heap dump, ignore it.
Expand Down Expand Up @@ -231,8 +237,6 @@ internal void SetupCallbacks(MemoryGraph memoryGraph, TraceEventDispatcher sourc
}
};



source.Clr.GCStop += delegate (GCEndTraceData data)
{
if (m_ignoreEvents || data.ProcessID != m_processId)
Expand Down Expand Up @@ -262,6 +266,17 @@ internal void SetupCallbacks(MemoryGraph memoryGraph, TraceEventDispatcher sourc
}
};

source.Clr.GCGenAwareEnd += delegate (GenAwareEndTraceData data)
{
m_ignoreEvents = true;
if (m_nodeBlocks.Count == 0 && m_typeBlocks.Count == 0 && m_edgeBlocks.Count == 0)
{
m_log.WriteLine("Found no node events, looking for another GC");
m_seenStart = false;
return;
}
};

source.Clr.TypeBulkType += delegate (GCBulkTypeTraceData data)
{
// Don't check m_ignoreEvents here, as BulkType events can be emitted by other events...such as the GC allocation event.
Expand Down Expand Up @@ -474,6 +489,9 @@ internal void SetupCallbacks(MemoryGraph memoryGraph, TraceEventDispatcher sourc
case 3:
segment.Gen3End = end;
break;
case 4:
segment.Gen4End = end;
break;
default:
throw new Exception("Invalid generation in GCGenerationRangeTraceData");
}
Expand Down
1 change: 1 addition & 0 deletions src/HeapDumpCommon/DotNetHeapInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ public class GCHeapDumpSegment : IFastSerializable
public Address Gen1End { get; internal set; }
public Address Gen2End { get; internal set; }
public Address Gen3End { get; internal set; }
public Address Gen4End { get; internal set; }

#region private
void IFastSerializable.ToStream(Serializer serializer)
Expand Down
5 changes: 5 additions & 0 deletions src/PerfView/PerfViewData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3770,6 +3770,11 @@ public override void Open(Window parentWindow, StatusBar worker, Action doAfter)
// For .NET, we are looking for a Gen 2 GC Start that is induced that has GCBulkNodes after it.
var lastGCStartsRelMSec = new Dictionary<int, double>();

source.Clr.GCGenAwareStart += delegate (Microsoft.Diagnostics.Tracing.Parsers.Clr.GenAwareBeginTraceData data)
{
lastGCStartsRelMSec[data.ProcessID] = data.TimeStampRelativeMSec;
};

source.Clr.GCStart += delegate (Microsoft.Diagnostics.Tracing.Parsers.Clr.GCStartTraceData data)
{
// Look for induced GCs. and remember their when it happened.
Expand Down
160 changes: 159 additions & 1 deletion src/TraceEvent/Parsers/ClrTraceEventParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,34 @@ internal ClrTraceEventParserState State
}
}

public event Action<GenAwareBeginTraceData> GCGenAwareStart
{
add
{
// action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
RegisterTemplate(GenAwareBeginTemplate(value));
}
remove
{
source.UnregisterEventTemplate(value, 206, ProviderGuid);
source.UnregisterEventTemplate(value, 206, GCTaskGuid);
}
}

public event Action<GenAwareEndTraceData> GCGenAwareEnd
{
add
{
// action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
RegisterTemplate(GenAwareEndTemplate(value));
}
remove
{
source.UnregisterEventTemplate(value, 207, ProviderGuid);
source.UnregisterEventTemplate(value, 207, GCTaskGuid);
}
}

public event Action<GCStartTraceData> GCStart
{
add
Expand Down Expand Up @@ -1998,6 +2026,14 @@ static private MethodJitMemoryAllocatedForCodeTraceData MethodMemoryAllocatedFor
{ // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
return new MethodJitMemoryAllocatedForCodeTraceData(action, 146, 9, "Method", Guid.Empty, 103, "MemoryAllocatedForJitCode", ProviderGuid, ProviderName);
}
static private GenAwareBeginTraceData GenAwareBeginTemplate(Action<GenAwareBeginTraceData> action)
{ // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
return new GenAwareBeginTraceData(action, 206, 1, "GC", GCTaskGuid, 1, "GenAwareStart", ProviderGuid, ProviderName);
}
static private GenAwareEndTraceData GenAwareEndTemplate(Action<GenAwareEndTraceData> action)
{ // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
return new GenAwareEndTraceData(action, 207, 1, "GC", GCTaskGuid, 2, "GenAwareEnd", ProviderGuid, ProviderName);
}
static private R2RGetEntryPointStartTraceData R2RGetEntryPointStartTemplate(Action<R2RGetEntryPointStartTraceData> action)
{ // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
return new R2RGetEntryPointStartTraceData(action, 160, 9, "Method", MethodTaskGuid, 33, "R2RGetEntryPointStart", ProviderGuid, ProviderName);
Expand All @@ -2016,7 +2052,7 @@ protected internal override void EnumerateTemplates(Func<string, string, EventFi
{
if (s_templates == null)
{
var templates = new TraceEvent[135];
var templates = new TraceEvent[137];
templates[0] = new GCStartTraceData(null, 1, 1, "GC", GCTaskGuid, 1, "Start", ProviderGuid, ProviderName);
templates[1] = new GCEndTraceData(null, 2, 1, "GC", GCTaskGuid, 2, "Stop", ProviderGuid, ProviderName);
templates[2] = new GCNoUserDataTraceData(null, 3, 1, "GC", GCTaskGuid, 132, "RestartEEStop", ProviderGuid, ProviderName);
Expand Down Expand Up @@ -2159,6 +2195,8 @@ protected internal override void EnumerateTemplates(Func<string, string, EventFi
templates[132] = TypeLoadStartTemplate(null);
templates[133] = TypeLoadStopTemplate(null);
templates[134] = MethodMemoryAllocatedForJitCodeTemplate(null);
templates[135] = GenAwareBeginTemplate(null);
templates[136] = GenAwareEndTemplate(null);

s_templates = templates;
}
Expand Down Expand Up @@ -2245,6 +2283,126 @@ private void RegisterTemplate(TraceEvent template)

namespace Microsoft.Diagnostics.Tracing.Parsers.Clr
{
public sealed class GenAwareBeginTraceData : TraceEvent
{
public int Count { get { return GetInt32At(0); } }
public int ClrInstanceID { get { return GetInt16At(4); } }

#region Private
internal GenAwareBeginTraceData(Action<GenAwareBeginTraceData> target, int eventID, int task, string taskName, Guid taskGuid, int opcode, string opcodeName, Guid providerGuid, string providerName)
: base(eventID, task, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName)
{
m_target = target;
}
protected internal override void Dispatch()
{
m_target(this);
}
protected internal override void Validate()
{
Debug.Assert(!(Version == 0 && EventDataLength != 6));
}
protected internal override Delegate Target
{
get { return m_target; }
set { m_target = (Action<GenAwareBeginTraceData>)value; }
}
public override StringBuilder ToXml(StringBuilder sb)
{
Prefix(sb);
XmlAttrib(sb, "Count", Count);
XmlAttrib(sb, "ClrInstanceID", ClrInstanceID);
sb.Append("/>");
return sb;
}

public override string[] PayloadNames
{
get
{
if (payloadNames == null)
payloadNames = new string[] { "Count", "ClrInstanceID" };
return payloadNames;
}
}

public override object PayloadValue(int index)
{
switch (index)
{
case 0:
return Count;
case 1:
return ClrInstanceID;
default:
Debug.Assert(false, "Bad field index");
return null;
}
}

private event Action<GenAwareBeginTraceData> m_target;
#endregion
}
public sealed class GenAwareEndTraceData : TraceEvent
{
public int Count { get { return GetInt32At(0); } }
public int ClrInstanceID { get { return GetInt16At(4); } }

#region Private
internal GenAwareEndTraceData(Action<GenAwareEndTraceData> target, int eventID, int task, string taskName, Guid taskGuid, int opcode, string opcodeName, Guid providerGuid, string providerName)
: base(eventID, task, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName)
{
m_target = target;
}
protected internal override void Dispatch()
{
m_target(this);
}
protected internal override void Validate()
{
Debug.Assert(!(Version == 0 && EventDataLength != 6));
}
protected internal override Delegate Target
{
get { return m_target; }
set { m_target = (Action<GenAwareEndTraceData>)value; }
}
public override StringBuilder ToXml(StringBuilder sb)
{
Prefix(sb);
XmlAttrib(sb, "Count", Count);
XmlAttrib(sb, "ClrInstanceID", ClrInstanceID);
sb.Append("/>");
return sb;
}

public override string[] PayloadNames
{
get
{
if (payloadNames == null)
payloadNames = new string[] { "Count", "ClrInstanceID" };
return payloadNames;
}
}

public override object PayloadValue(int index)
{
switch (index)
{
case 0:
return Count;
case 1:
return ClrInstanceID;
default:
Debug.Assert(false, "Bad field index");
return null;
}
}

private event Action<GenAwareEndTraceData> m_target;
#endregion
}
public sealed class GCStartTraceData : TraceEvent
{
public int Count { get { return GetInt32At(0); } }
Expand Down