Skip to content

Commit b669d1b

Browse files
committed
Remove non-functioning StartStopMingledComputer in favor of better factored stats page
1 parent 7bc4c9e commit b669d1b

File tree

5 files changed

+153
-514
lines changed

5 files changed

+153
-514
lines changed

src/PerfView/PerfViewData.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3564,9 +3564,7 @@ protected override void WriteHtmlBody(TraceLog dataFile, TextWriter writer, stri
35643564
using (var source = dataFile.Events.GetSource())
35653565
{
35663566
CLRRuntimeActivityComputer runtimeLoaderComputer = new CLRRuntimeActivityComputer(source);
3567-
var stackSource = new MutableTraceEventStackSource(source.TraceLog);
3568-
StartStopStackMingledComputer mingledComputer = new StartStopStackMingledComputer(stackSource, null, true, source, runtimeLoaderComputer.StartStopEvents);
3569-
m_PerThreadData = mingledComputer.StartStopData;
3567+
m_PerThreadData = runtimeLoaderComputer.StartStopData;
35703568
m_interestingProcesses = new Dictionary<int, Microsoft.Diagnostics.Tracing.Analysis.TraceProcess>();
35713569

35723570
Microsoft.Diagnostics.Tracing.Analysis.TraceLoadedDotNetRuntimeExtensions.NeedLoadedDotNetRuntimes(source);
@@ -4371,10 +4369,6 @@ protected internal override StackSource OpenStackSourceImpl(string streamName, T
43714369
{
43724370
return eventLog.ThreadTimeStacks();
43734371
}
4374-
else if (streamName == "Runtime Loader (CPU Time)")
4375-
{
4376-
return eventLog.RuntimeLoaderStacks();
4377-
}
43784372
else if (streamName == "Processes / Files / Registry")
43794373
{
43804374
return GetProcessFileRegistryStackSource(eventSource, log);

src/PerfView/RuntimeLoaderStats.cs

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public static void ToTxt(string filePath, TraceProcess process, Microsoft.Diagno
9999

100100

101101
writer.Write($"{startTime.ToString("F3").PadLeft(12)}~{inclusiveTimeStr.PadLeft(9)}~{exclusiveTime.ToString("F3").PadLeft(9)}~");
102-
int stackDepth = CountStackDepth(runtimeOps, eventData) - 3;
102+
int stackDepth = eventData.StackDepth;
103103
for (int iStackDepth = 0; iStackDepth < stackDepth; iStackDepth++)
104104
writer.Write(" |");
105105

@@ -108,7 +108,7 @@ public static void ToTxt(string filePath, TraceProcess process, Microsoft.Diagno
108108
else
109109
writer.Write("--");
110110

111-
writer.WriteLine(runtimeOps.StackSource.GetFrameName(eventData.NameFrame, false));
111+
writer.WriteLine(eventData.Name, false);
112112
seenEvents.Add(eventData.End.EventId);
113113
}
114114
}
@@ -151,18 +151,5 @@ public static double TotalCPUMSec(Microsoft.Diagnostics.Tracing.Analysis.TracePr
151151

152152
return cpuTime;
153153
}
154-
155-
private static int CountStackDepth(Microsoft.Diagnostics.Tracing.RuntimeLoaderStats runtimeOps, StartStopStackMingledComputer.StartStopThreadEventData data)
156-
{
157-
var currentStack = data.OutputStacks.ReplacementStack;
158-
int depthCount = 0;
159-
160-
for (;currentStack != StackSourceCallStackIndex.Invalid; currentStack = runtimeOps.StackSource.GetCallerIndex(currentStack))
161-
{
162-
depthCount++;
163-
}
164-
165-
return depthCount;
166-
}
167154
}
168155
}

src/PerfView/UserCommands.cs

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1874,38 +1874,6 @@ public static MutableTraceEventStackSource ThreadTimeStacks(this TraceLog eventL
18741874
return stackSource;
18751875
}
18761876

1877-
public static StackSource RuntimeLoaderStacks(this TraceLog eventLog, TraceProcess process = null, Predicate<TraceEvent> predicate = null)
1878-
{
1879-
TraceEvents events;
1880-
if (process == null)
1881-
{
1882-
events = eventLog.Events.Filter((x) => ((predicate == null) || predicate(x)) && x is SampledProfileTraceData && x.ProcessID != 0);
1883-
}
1884-
else
1885-
{
1886-
events = process.EventsInProcess.Filter((x) => ((predicate == null) || predicate(x)) && x is SampledProfileTraceData);
1887-
}
1888-
1889-
var stackSource = new MutableTraceEventStackSource(eventLog);
1890-
stackSource.ShowUnknownAddresses = App.CommandLineArgs.ShowUnknownAddresses;
1891-
1892-
StackSourceSample sample = new StackSourceSample(stackSource);
1893-
foreach (var event_ in ((IEnumerable<TraceEvent>)events))
1894-
{
1895-
sample.TimeRelativeMSec = event_.TimeStampRelativeMSec;
1896-
sample.StackIndex = stackSource.GetCallStack(event_.CallStackIndex(), event_);
1897-
stackSource.AddSample(sample);
1898-
};
1899-
stackSource.DoneAddingSamples();
1900-
1901-
CLRRuntimeActivityComputer runtimeLoaderComputer = new CLRRuntimeActivityComputer(eventLog.Events.GetSource());
1902-
1903-
var finalStackSource = new MutableTraceEventStackSource(eventLog);
1904-
StartStopStackMingledComputer mingledComputer = new StartStopStackMingledComputer(finalStackSource, stackSource, false, eventLog.Events.GetSource(), runtimeLoaderComputer.StartStopEvents);
1905-
1906-
return CopyStackSource.Clone(finalStackSource);
1907-
}
1908-
19091877
public static MutableTraceEventStackSource ThreadTimeWithReadyThreadStacks(this TraceLog eventLog, TraceProcess process = null)
19101878
{
19111879
var stackSource = new MutableTraceEventStackSource(eventLog);

src/TraceEvent/Computers/CLRRuntimeActivityComputer.cs

Lines changed: 150 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,76 @@
2020

2121
namespace Microsoft.Diagnostics.Tracing
2222
{
23+
public class RuntimeLoaderStats : Dictionary<int, CLRRuntimeActivityComputer.PerThreadStartStopData>
24+
{
25+
public TraceLogEventSource EventSource;
26+
}
27+
28+
2329
public class CLRRuntimeActivityComputer
2430
{
31+
public struct EventUID : IComparable<EventUID>, IEquatable<EventUID>
32+
{
33+
public EventUID(TraceEvent evt) : this(evt.EventIndex, evt.TimeStampRelativeMSec) { }
34+
35+
public EventUID(EventIndex eventId, double time)
36+
{
37+
EventId = eventId;
38+
Time = time;
39+
}
40+
41+
public readonly EventIndex EventId;
42+
public readonly double Time;
43+
44+
public int CompareTo(EventUID other)
45+
{
46+
int timeCompare = Time.CompareTo(other.Time);
47+
if (timeCompare != 0)
48+
return timeCompare;
49+
50+
return EventId.CompareTo(other.EventId);
51+
}
52+
53+
public override int GetHashCode()
54+
{
55+
return (int)EventId;
56+
}
57+
58+
public override bool Equals(object obj)
59+
{
60+
if (!(obj is EventUID))
61+
return false;
62+
return this.CompareTo((EventUID)obj) == 0;
63+
}
64+
65+
public bool Equals(EventUID other)
66+
{
67+
return this.CompareTo(other) == 0;
68+
}
69+
}
70+
71+
public struct StartStopThreadEventData : IComparable<StartStopThreadEventData>
72+
{
73+
public StartStopThreadEventData(EventUID start, EventUID end, string name)
74+
{
75+
Start = start;
76+
End = end;
77+
Name = name;
78+
StackDepth = 0;
79+
}
80+
81+
public EventUID Start;
82+
public EventUID End;
83+
public int StackDepth;
84+
public string Name;
85+
86+
int IComparable<StartStopThreadEventData>.CompareTo(StartStopThreadEventData other)
87+
{
88+
return Start.CompareTo(other.Start);
89+
}
90+
}
91+
92+
2593
struct IdOfIncompleteAction : IEquatable<IdOfIncompleteAction>
2694
{
2795
public long Identifier;
@@ -48,19 +116,32 @@ public bool Equals(IdOfIncompleteAction other)
48116

49117
struct IncompleteActionDesc
50118
{
51-
public StartStopStackMingledComputer.EventUID Start;
119+
public EventUID Start;
52120
public string OperationType;
53121
public string Name;
54122
}
55123

124+
public class PerThreadStartStopData
125+
{
126+
public int Offset;
127+
128+
public StartStopThreadEventData[] Data;
129+
public StartStopThreadEventData[] SplitUpData;
130+
public double[] SplitUpDataStarts;
131+
}
132+
133+
RuntimeLoaderStats _startStopData = new RuntimeLoaderStats();
134+
public RuntimeLoaderStats StartStopData => _startStopData;
135+
56136
Dictionary<IdOfIncompleteAction, IncompleteActionDesc> _incompleteJitEvents = new Dictionary<IdOfIncompleteAction, IncompleteActionDesc>();
57137
Dictionary<IdOfIncompleteAction, IncompleteActionDesc> _incompleteR2REvents = new Dictionary<IdOfIncompleteAction, IncompleteActionDesc>();
58138
Dictionary<IdOfIncompleteAction, IncompleteActionDesc> _incompleteTypeLoadEvents = new Dictionary<IdOfIncompleteAction, IncompleteActionDesc>();
59139

60-
public Dictionary<int, List<StartStopStackMingledComputer.StartStopThreadEventData>> StartStopEvents { get; } = new Dictionary<int, List<StartStopStackMingledComputer.StartStopThreadEventData>>();
140+
public Dictionary<int, List<StartStopThreadEventData>> StartStopEvents { get; } = new Dictionary<int, List<StartStopThreadEventData>>();
61141

62142
public CLRRuntimeActivityComputer(TraceLogEventSource source)
63143
{
144+
_startStopData.EventSource = source;
64145
source.Clr.MethodJittingStarted += Clr_MethodJittingStarted;
65146
source.Clr.MethodR2RGetEntryPoint += Clr_MethodR2RGetEntryPoint;
66147
source.Clr.MethodLoadVerbose += Clr_MethodLoadVerbose;
@@ -78,21 +159,74 @@ public CLRRuntimeActivityComputer(TraceLogEventSource source)
78159
source.Clr.LoaderAssemblyLoad -= Clr_LoaderAssemblyLoad;
79160
source.Clr.TypeLoadStart -= Clr_TypeLoadStart;
80161
source.Clr.TypeLoadStop -= Clr_TypeLoadStop;
162+
163+
HashSet<EventUID> interestingEvents = new HashSet<EventUID>();
164+
foreach (var entry in StartStopEvents)
165+
{
166+
StartStopThreadEventData[] data = entry.Value.ToArray();
167+
Array.Sort(data);
168+
PerThreadStartStopData perThread = new PerThreadStartStopData();
169+
perThread.Data = data;
170+
for (int i = 0; i < data.Length; i++)
171+
{
172+
interestingEvents.Add(data[i].Start);
173+
interestingEvents.Add(data[i].End);
174+
}
175+
_startStopData.Add(entry.Key, perThread);
176+
}
177+
178+
foreach (var entry in _startStopData)
179+
{
180+
List<StartStopThreadEventData> splitUpStartStopData = new List<StartStopThreadEventData>();
181+
182+
Stack<StartStopThreadEventData> currentPerThreadProcessingState = new Stack<StartStopThreadEventData>();
183+
for (int i = 0; i < entry.Value.Data.Length; i++)
184+
{
185+
var startStop = entry.Value.Data[i];
186+
187+
if (currentPerThreadProcessingState.Count > 0)
188+
{
189+
while ((currentPerThreadProcessingState.Count > 0) && (currentPerThreadProcessingState.Peek().End.CompareTo(startStop.Start) < 0))
190+
{
191+
// Current stack top event finished before this event happened.
192+
var poppedEvent = currentPerThreadProcessingState.Pop();
193+
EventUID lastEventProcessedEnd = poppedEvent.End;
194+
if (currentPerThreadProcessingState.Count > 0)
195+
{
196+
var tempPoppedEvent = currentPerThreadProcessingState.Pop();
197+
tempPoppedEvent.Start = lastEventProcessedEnd;
198+
splitUpStartStopData.Add(tempPoppedEvent);
199+
currentPerThreadProcessingState.Push(tempPoppedEvent);
200+
}
201+
}
202+
}
203+
204+
startStop.StackDepth = currentPerThreadProcessingState.Count;
205+
splitUpStartStopData.Add(startStop);
206+
currentPerThreadProcessingState.Push(startStop);
207+
}
208+
entry.Value.SplitUpData = splitUpStartStopData.ToArray();
209+
entry.Value.SplitUpDataStarts = new double[entry.Value.SplitUpData.Length];
210+
for (int i = 0; i < entry.Value.SplitUpDataStarts.Length; i++)
211+
{
212+
entry.Value.SplitUpDataStarts[i] = entry.Value.SplitUpData[i].Start.Time;
213+
}
214+
}
81215
}
82216

83-
private void AddStartStopData(int threadId, StartStopStackMingledComputer.EventUID start, StartStopStackMingledComputer.EventUID end, string name)
217+
private void AddStartStopData(int threadId, EventUID start, EventUID end, string name)
84218
{
85219
if (!StartStopEvents.ContainsKey(threadId))
86-
StartStopEvents[threadId] = new List<StartStopStackMingledComputer.StartStopThreadEventData>();
220+
StartStopEvents[threadId] = new List<StartStopThreadEventData>();
87221

88-
List<StartStopStackMingledComputer.StartStopThreadEventData> startStopData = StartStopEvents[threadId];
89-
startStopData.Add(new StartStopStackMingledComputer.StartStopThreadEventData(start, end, name));
222+
List<StartStopThreadEventData> startStopData = StartStopEvents[threadId];
223+
startStopData.Add(new StartStopThreadEventData(start, end, name));
90224
}
91225

92226
private void Clr_LoaderAssemblyLoad(AssemblyLoadUnloadTraceData obj)
93227
{
94228
// Since we don't have start stop data, simply treat the assembly load event as a point in time so that it is visible in the textual load view
95-
StartStopStackMingledComputer.EventUID eventTime = new StartStopStackMingledComputer.EventUID(obj);
229+
EventUID eventTime = new EventUID(obj);
96230
AddStartStopData(obj.ThreadID, eventTime, eventTime, $"ASMLOAD({obj.FullyQualifiedAssemblyName},{obj.AssemblyID})");
97231
}
98232

@@ -116,14 +250,14 @@ private void MethodJittedEvent(TraceEvent evt, long methodID)
116250
// JitStart is processed, don't process it again.
117251
_incompleteJitEvents.Remove(id);
118252

119-
AddStartStopData(id.ThreadID, jitStartData.Start, new StartStopStackMingledComputer.EventUID(evt), jitStartData.OperationType + "(" + jitStartData.Name + ")");
253+
AddStartStopData(id.ThreadID, jitStartData.Start, new EventUID(evt), jitStartData.OperationType + "(" + jitStartData.Name + ")");
120254
}
121255
}
122256

123257
private void Clr_MethodJittingStarted(MethodJittingStartedTraceData obj)
124258
{
125259
IncompleteActionDesc incompleteDesc = new IncompleteActionDesc();
126-
incompleteDesc.Start = new StartStopStackMingledComputer.EventUID(obj);
260+
incompleteDesc.Start = new EventUID(obj);
127261
incompleteDesc.Name = JITStats.GetMethodName(obj);
128262
incompleteDesc.OperationType = "JIT";
129263

@@ -137,7 +271,7 @@ private void Clr_MethodJittingStarted(MethodJittingStartedTraceData obj)
137271
private void Clr_R2RGetEntryPointStarted(R2RGetEntryPointStartedTraceData obj)
138272
{
139273
IncompleteActionDesc incompleteDesc = new IncompleteActionDesc();
140-
incompleteDesc.Start = new StartStopStackMingledComputer.EventUID(obj);
274+
incompleteDesc.Start = new EventUID(obj);
141275
incompleteDesc.Name = "";
142276
incompleteDesc.OperationType = "R2R";
143277

@@ -156,7 +290,7 @@ private void Clr_MethodR2RGetEntryPoint(R2RGetEntryPointTraceData obj)
156290

157291
// If we had a R2R start lookup event, capture that start time, otherwise, use the R2REntrypoint
158292
// data as both start and stop
159-
StartStopStackMingledComputer.EventUID startUID = new StartStopStackMingledComputer.EventUID(obj);
293+
EventUID startUID = new EventUID(obj);
160294
if (_incompleteR2REvents.TryGetValue(id, out IncompleteActionDesc r2rStartData))
161295
{
162296
startUID = r2rStartData.Start;
@@ -166,18 +300,18 @@ private void Clr_MethodR2RGetEntryPoint(R2RGetEntryPointTraceData obj)
166300
if (obj.EntryPoint == 0)
167301
{
168302
// If Entrypoint is null then the search failed.
169-
AddStartStopData(id.ThreadID, startUID, new StartStopStackMingledComputer.EventUID(obj), "R2R_Failed" + "(" + JITStats.GetMethodName(obj) + ")");
303+
AddStartStopData(id.ThreadID, startUID, new EventUID(obj), "R2R_Failed" + "(" + JITStats.GetMethodName(obj) + ")");
170304
}
171305
else
172306
{
173-
AddStartStopData(id.ThreadID, startUID, new StartStopStackMingledComputer.EventUID(obj), "R2R_Found" + "(" + JITStats.GetMethodName(obj) + ")");
307+
AddStartStopData(id.ThreadID, startUID, new EventUID(obj), "R2R_Found" + "(" + JITStats.GetMethodName(obj) + ")");
174308
}
175309
}
176310

177311
private void Clr_TypeLoadStart(TypeLoadStartTraceData obj)
178312
{
179313
IncompleteActionDesc incompleteDesc = new IncompleteActionDesc();
180-
incompleteDesc.Start = new StartStopStackMingledComputer.EventUID(obj);
314+
incompleteDesc.Start = new EventUID(obj);
181315
incompleteDesc.Name = "";
182316
incompleteDesc.OperationType = "TypeLoad";
183317

@@ -196,14 +330,14 @@ private void Clr_TypeLoadStop(TypeLoadStopTraceData obj)
196330

197331
// If we had a TypeLoad start lookup event, capture that start time, otherwise, use the TypeLoadStop
198332
// data as both start and stop
199-
StartStopStackMingledComputer.EventUID startUID = new StartStopStackMingledComputer.EventUID(obj);
333+
EventUID startUID = new EventUID(obj);
200334
if (_incompleteTypeLoadEvents.TryGetValue(id, out IncompleteActionDesc typeLoadStartData))
201335
{
202336
startUID = typeLoadStartData.Start;
203337
_incompleteTypeLoadEvents.Remove(id);
204338
}
205339

206-
AddStartStopData(id.ThreadID, startUID, new StartStopStackMingledComputer.EventUID(obj), $"TypeLoad ({obj.TypeName}, {obj.LoadLevel})");
340+
AddStartStopData(id.ThreadID, startUID, new EventUID(obj), $"TypeLoad ({obj.TypeName}, {obj.LoadLevel})");
207341
}
208342
}
209343
}

0 commit comments

Comments
 (0)