Skip to content

Commit 0c79248

Browse files
committed
Provide control over what events are visible, and cleanup codebase
1 parent b669d1b commit 0c79248

File tree

3 files changed

+114
-59
lines changed

3 files changed

+114
-59
lines changed

src/PerfView/PerfViewData.cs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,11 @@ protected virtual string DoCommand(string command, StatusBar worker, out Action
10611061
return DoCommand(command, worker);
10621062
}
10631063

1064+
protected virtual string DoCommand(Uri commandUri, StatusBar worker, out Action continuation)
1065+
{
1066+
return DoCommand(commandUri.LocalPath, worker, out continuation);
1067+
}
1068+
10641069
public override void Open(Window parentWindow, StatusBar worker, Action doAfter)
10651070
{
10661071
if (Viewer == null)
@@ -1087,7 +1092,7 @@ public override void Open(Window parentWindow, StatusBar worker, Action doAfter)
10871092
Viewer.StatusBar.StartWork("Following Hyperlink", delegate ()
10881093
{
10891094
Action continuation;
1090-
var message = DoCommand(e.Uri.LocalPath, Viewer.StatusBar, out continuation);
1095+
var message = DoCommand(e.Uri, Viewer.StatusBar, out continuation);
10911096
Viewer.StatusBar.EndWork(delegate ()
10921097
{
10931098
if (message != null)
@@ -3534,22 +3539,52 @@ protected override void WriteHtmlBody(TraceLog dataFile, TextWriter writer, stri
35343539
public class PerfViewRuntimeLoaderStats : PerfViewHtmlReport
35353540
{
35363541
public PerfViewRuntimeLoaderStats(PerfViewFile dataFile) : base(dataFile, "Runtime Loader") { }
3537-
protected override string DoCommand(string command, StatusBar worker)
3542+
protected override string DoCommand(Uri commandUri, StatusBar worker, out Action continuation)
35383543
{
3544+
continuation = null;
3545+
3546+
string command = commandUri.LocalPath;
35393547
string textStr = "txt/";
35403548

35413549
if (command.StartsWith(textStr))
35423550
{
35433551
var rest = command.Substring(textStr.Length);
3552+
3553+
3554+
bool tree = true;
3555+
List<string> filters = null;
3556+
if (!String.IsNullOrEmpty(commandUri.Query))
3557+
{
3558+
filters = new List<string>();
3559+
tree = commandUri.Query.Contains("TreeView");
3560+
if (commandUri.Query.Contains("JIT"))
3561+
filters.Add("JIT");
3562+
if (commandUri.Query.Contains("R2R_Found"))
3563+
filters.Add("R2R_Found");
3564+
if (commandUri.Query.Contains("R2R_Failed"))
3565+
filters.Add("R2R_Failed");
3566+
if (commandUri.Query.Contains("TypeLoad"))
3567+
filters.Add("TypeLoad");
3568+
if (commandUri.Query.Contains("AssemblyLoad"))
3569+
filters.Add("AssemblyLoad");
3570+
}
3571+
string identifier = $"{(tree?"Tree":"Flat")}_";
3572+
if (filters != null)
3573+
{
3574+
foreach (var filter in filters)
3575+
{
3576+
identifier = identifier + "_" + filter;
3577+
}
3578+
}
35443579
var processId = int.Parse(rest);
35453580
if (m_interestingProcesses.ContainsKey(processId))
35463581
{
35473582
var proc = m_interestingEtlxProcesses[processId];
3548-
var txtFile = CacheFiles.FindFile(FilePath, ".runtimeLoaderstats." + processId.ToString() + ".txt");
3583+
var txtFile = CacheFiles.FindFile(FilePath, ".runtimeLoaderstats." + processId.ToString() + "_" + identifier + ".txt");
35493584
if (!File.Exists(txtFile) || File.GetLastWriteTimeUtc(txtFile) < File.GetLastWriteTimeUtc(FilePath) ||
35503585
File.GetLastWriteTimeUtc(txtFile) < File.GetLastWriteTimeUtc(SupportFiles.MainAssemblyPath))
35513586
{
3552-
Stats.RuntimeLoaderStats.ToTxt(txtFile, proc, m_PerThreadData);
3587+
Stats.RuntimeLoaderStats.ToTxt(txtFile, proc, m_PerThreadData, filters.ToArray(), tree);
35533588
}
35543589
Command.Run(Command.Quote(txtFile), new CommandOptions().AddStart().AddTimeout(CommandOptions.Infinite));
35553590
System.Threading.Thread.Sleep(500); // Give it time to start a bit.
@@ -7362,12 +7397,6 @@ protected override Action<Action> OpenImpl(Window parentWindow, StatusBar worker
73627397

73637398
advanced.Children.Add(new PerfViewJitStats(this));
73647399
advanced.Children.Add(new PerfViewRuntimeLoaderStats(this));
7365-
7366-
if (hasCPUStacks)
7367-
{
7368-
advanced.Children.Add(new PerfViewStackSource(this, "Runtime Loader (CPU Time)"));
7369-
}
7370-
73717400
advanced.Children.Add(new PerfViewEventStats(this));
73727401

73737402
m_Children.Add(new PerfViewEventSource(this));

src/PerfView/RuntimeLoaderStats.cs

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,31 @@ public static void ToHtml(TextWriter writer, Microsoft.Diagnostics.Tracing.Analy
5050
writer.WriteLine("<LI>Raw data:");
5151
writer.WriteLine("<UL>");
5252
{
53-
writer.WriteLine("<LI>Individual Runtime Operation Events <A HREF=\"command:txt/{0}\">Txt</A></LI>", stats.ProcessID);
53+
writer.WriteLine($@"
54+
<form action=""command:txt/{stats.ProcessID}"">
55+
<input type=""checkbox"" checked=""yes"" id=""TreeView"" name=""TreeView"" value=""true"">
56+
<label for=""TreeView"">Show data as a tree</label>
57+
<input type=""checkbox"" checked=""yes"" id=""JIT"" name=""JIT"" value=""true"">
58+
<label for=""JIT"">Show JIT data</label>
59+
<input type=""checkbox"" checked=""yes"" id=""R2R_Found"" name=""R2R_Found"" value=""true"">
60+
<label for=""R2R_Found"">Show R2R found data</label>
61+
<input type=""checkbox"" id=""R2R_Failed"" name=""R2R_Failed"" value=""true"">
62+
<label for=""R2R_Failed"">Show R2R not found data</label>
63+
<input type=""checkbox"" checked=""yes"" id=""TypeLoad"" name=""TypeLoad"" value=""true"">
64+
<label for=""TypeLoad"">Show TypeLoad data</label>
65+
<input type=""checkbox"" checked=""yes"" id=""AssemblyLoad"" name=""AssemblyLoad"" value=""true"">
66+
<label for=""AssemblyLoad"">Show AssemblyLoad data</label>
67+
<input type=""submit"" value=""Submit"">
68+
</form>
69+
");
5470
}
5571
writer.WriteLine("</UL>");
5672
writer.WriteLine("</LI>");
5773
}
5874
writer.WriteLine("</UL>");
5975
}
6076

61-
public static void ToTxt(string filePath, TraceProcess process, Microsoft.Diagnostics.Tracing.RuntimeLoaderStats runtimeOps)
77+
public static void ToTxt(string filePath, TraceProcess process, Microsoft.Diagnostics.Tracing.RuntimeLoaderStats runtimeOps, string[] filters, bool tree)
6278
{
6379
using (var writer = File.CreateText(filePath))
6480
{
@@ -76,18 +92,28 @@ public static void ToTxt(string filePath, TraceProcess process, Microsoft.Diagno
7692

7793
HashSet<EventIndex> seenEvents = new HashSet<EventIndex>();
7894

79-
for (int i = 0; i < runtimeOps[threadId].SplitUpData.Length; i++)
95+
IEnumerable<CLRRuntimeActivityComputer.StartStopThreadEventData> dataToProcess = runtimeOps[threadId].Data;
96+
97+
if (filters != null)
98+
dataToProcess = CLRRuntimeActivityComputer.PerThreadStartStopData.FilterData(filters, dataToProcess);
99+
100+
if (tree)
101+
dataToProcess = CLRRuntimeActivityComputer.PerThreadStartStopData.Stackify(dataToProcess);
102+
103+
var perThreadData = new List<CLRRuntimeActivityComputer.StartStopThreadEventData>(dataToProcess);
104+
105+
for (int i = 0; i < perThreadData.Count; i++)
80106
{
81-
var eventData = runtimeOps[threadId].SplitUpData[i];
107+
var eventData = perThreadData[i];
82108
double startTime = eventData.Start.Time;
83109
double endTime = eventData.End.Time;
84110
double inclusiveTime = endTime - startTime;
85111
double exclusiveTime = inclusiveTime;
86112
string inclusiveTimeStr = inclusiveTime.ToString("F3");
87113

88-
if (runtimeOps[threadId].SplitUpData.Length > (i + 1))
114+
if (perThreadData.Count > (i + 1))
89115
{
90-
double startOfNextItem = runtimeOps[threadId].SplitUpData[i + 1].Start.Time;
116+
double startOfNextItem = perThreadData[i + 1].Start.Time;
91117
if (startOfNextItem < endTime)
92118
{
93119
exclusiveTime = startOfNextItem - startTime;
@@ -138,7 +164,7 @@ public static double TotalCPUMSec(Microsoft.Diagnostics.Tracing.Analysis.TracePr
138164
double lastThreadTimeSeen = double.MinValue;
139165
if (runtimeOps.ContainsKey(threadId))
140166
{
141-
foreach (var eventData in runtimeOps[threadId].SplitUpData)
167+
foreach (var eventData in runtimeOps[threadId].Data)
142168
{
143169
if (lastThreadTimeSeen >= eventData.End.Time)
144170
continue;

src/TraceEvent/Computers/CLRRuntimeActivityComputer.cs

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ public class RuntimeLoaderStats : Dictionary<int, CLRRuntimeActivityComputer.Per
2525
public TraceLogEventSource EventSource;
2626
}
2727

28-
2928
public class CLRRuntimeActivityComputer
3029
{
3130
public struct EventUID : IComparable<EventUID>, IEquatable<EventUID>
@@ -126,8 +125,47 @@ public class PerThreadStartStopData
126125
public int Offset;
127126

128127
public StartStopThreadEventData[] Data;
129-
public StartStopThreadEventData[] SplitUpData;
130-
public double[] SplitUpDataStarts;
128+
129+
public static IEnumerable<StartStopThreadEventData> FilterData(string[] filters, IEnumerable<StartStopThreadEventData> inputStream)
130+
{
131+
foreach (var input in inputStream)
132+
{
133+
foreach (var filter in filters)
134+
{
135+
if (input.Name.StartsWith(filter))
136+
yield return input;
137+
}
138+
}
139+
}
140+
141+
public static IEnumerable<StartStopThreadEventData> Stackify(IEnumerable<StartStopThreadEventData> inputStream)
142+
{
143+
Stack<StartStopThreadEventData> currentPerThreadProcessingState = new Stack<StartStopThreadEventData>();
144+
foreach (var startStopIn in inputStream)
145+
{
146+
var startStop = startStopIn;
147+
if (currentPerThreadProcessingState.Count > 0)
148+
{
149+
while ((currentPerThreadProcessingState.Count > 0) && (currentPerThreadProcessingState.Peek().End.CompareTo(startStop.Start) < 0))
150+
{
151+
// Current stack top event finished before this event happened.
152+
var poppedEvent = currentPerThreadProcessingState.Pop();
153+
EventUID lastEventProcessedEnd = poppedEvent.End;
154+
if (currentPerThreadProcessingState.Count > 0)
155+
{
156+
var tempPoppedEvent = currentPerThreadProcessingState.Pop();
157+
tempPoppedEvent.Start = lastEventProcessedEnd;
158+
yield return tempPoppedEvent;
159+
currentPerThreadProcessingState.Push(tempPoppedEvent);
160+
}
161+
}
162+
}
163+
164+
startStop.StackDepth = currentPerThreadProcessingState.Count;
165+
yield return startStop;
166+
currentPerThreadProcessingState.Push(startStop);
167+
}
168+
}
131169
}
132170

133171
RuntimeLoaderStats _startStopData = new RuntimeLoaderStats();
@@ -174,44 +212,6 @@ public CLRRuntimeActivityComputer(TraceLogEventSource source)
174212
}
175213
_startStopData.Add(entry.Key, perThread);
176214
}
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-
}
215215
}
216216

217217
private void AddStartStopData(int threadId, EventUID start, EventUID end, string name)
@@ -227,7 +227,7 @@ private void Clr_LoaderAssemblyLoad(AssemblyLoadUnloadTraceData obj)
227227
{
228228
// 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
229229
EventUID eventTime = new EventUID(obj);
230-
AddStartStopData(obj.ThreadID, eventTime, eventTime, $"ASMLOAD({obj.FullyQualifiedAssemblyName},{obj.AssemblyID})");
230+
AddStartStopData(obj.ThreadID, eventTime, eventTime, $"AssemblyLoad({obj.FullyQualifiedAssemblyName},{obj.AssemblyID})");
231231
}
232232

233233
private void Clr_MethodLoad(MethodLoadUnloadTraceData obj)

0 commit comments

Comments
 (0)