Skip to content

Commit c752369

Browse files
author
Vance Morrison
committed
Minor features. See release notes for 2.0.27 for details.
1 parent 34342e4 commit c752369

File tree

8 files changed

+436
-83
lines changed

8 files changed

+436
-83
lines changed

src/Directory.Build.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222

2323
<PropertyGroup>
2424
<!-- These are the versions of the things we are CREATING in this repository -->
25-
<PerfViewVersion>2.0.26</PerfViewVersion>
26-
<TraceEventVersion>2.0.26</TraceEventVersion>
25+
<PerfViewVersion>2.0.27</PerfViewVersion>
26+
<TraceEventVersion>2.0.27</TraceEventVersion>
2727
</PropertyGroup>
2828

2929
<!-- versions of dependencies that more than one project use -->

src/PerfView/CommandLineArgs.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,16 +101,16 @@ public static string GetHelpString(int maxLineWidth)
101101
public string StopOnEventLogMessage; // stop collection on event logs
102102
public string StopCommand; // is executed when a stop is triggered.
103103
public int StopOnAppFabricOverMsec;
104-
public int DelayAfterTriggerSec = 5; // Number of seconds to wait after a trigger
104+
public int DelayAfterTriggerSec = 5; // Number of seconds to wait after a trigger
105105
public string[] MonitorPerfCounter; // logs perf counters to the ETL file.
106106

107107
// Start options.
108-
public bool StackCompression; // Used compresses stacks when collecting traces.
108+
public bool StackCompression = true; // Use compresses stacks when collecting traces.
109109
public int BufferSizeMB = 256;
110110
public int CircularMB;
111111
public bool InMemoryCircularBuffer; // Uses EVENT_TRACE_BUFFERING_MODE for an in-memory circular buffer
112112
public KernelTraceEventParser.Keywords KernelEvents = KernelTraceEventParser.Keywords.Default;
113-
public string[] CpuCounters; // Specifies any profile sources (CPU counters) to turn on (Win 8 only)
113+
public string[] CpuCounters; // Specifies any profile sources (CPU counters) to turn on (Win 8 only)
114114
public ClrTraceEventParser.Keywords ClrEvents = ClrTraceEventParser.Keywords.Default;
115115
public TraceEventLevel ClrEventLevel = Microsoft.Diagnostics.Tracing.TraceEventLevel.Verbose; // The verbosity of CLR events
116116
public TplEtwProviderTraceEventParser.Keywords TplEvents = TplEtwProviderTraceEventParser.Keywords.Default;
@@ -514,8 +514,15 @@ private void SetupCommandLine(CommandLineParser parser)
514514
parser.DefineOptionalQualifier("SafeMode", ref SafeMode, "Turn off parallelism and other risky features.");
515515
parser.DefineOptionalQualifier("RestartingToElevelate", ref RestartingToElevelate, "Internal: indicates that perfView is restarting to get Admin privileges.");
516516

517-
// TODO FIX NOW this is a hack, does not handle kernel mode ...
518-
parser.DefineOptionalQualifier("SessionName", ref CommandProcessor.s_UserModeSessionName, "Define the name for the user mode session, if kernel events are off.");
517+
string sessionName = null;
518+
parser.DefineOptionalQualifier("SessionName", ref sessionName, "Define the name for the user mode session, if kernel events are off.");
519+
if (sessionName != null)
520+
{
521+
if (Environment.OSVersion.Version.Major * 10 + Environment.OSVersion.Version.Minor < 62)
522+
throw new ApplicationException("SessionName qualifier only works on Windows 8 and above.");
523+
CommandProcessor.s_UserModeSessionName = sessionName;
524+
CommandProcessor.s_KernelessionName = sessionName + "Kernel";
525+
}
519526

520527
parser.DefineOptionalQualifier("MaxNodeCountK", ref MaxNodeCountK,
521528
"The maximum number of objects (in K or thousands) that will even be examined when dumping the heap. Avoids memory use at collection time. " +

src/PerfView/CommandProcessor.cs

Lines changed: 71 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ public void Start(CommandLineArgs parsedArgs)
430430
LogFile.WriteLine("[Kernel Log: {0}]", Path.GetFullPath(kernelFileName));
431431
}
432432

433-
using (TraceEventSession kernelModeSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName, kernelFileName))
433+
using (TraceEventSession kernelModeSession = new TraceEventSession(s_KernelessionName, kernelFileName))
434434
{
435435
if (parsedArgs.CpuCounters != null)
436436
{
@@ -540,7 +540,7 @@ public void Start(CommandLineArgs parsedArgs)
540540
PerfViewLogger.Log.StartTracing();
541541
PerfViewLogger.StartTime = DateTime.UtcNow;
542542

543-
PerfViewLogger.Log.SessionParameters(KernelTraceEventParser.KernelSessionName, kernelFileName ?? "",
543+
PerfViewLogger.Log.SessionParameters(s_KernelessionName, kernelFileName ?? "",
544544
kernelModeSession.BufferSizeMB, kernelModeSession.CircularBufferMB);
545545
PerfViewLogger.Log.KernelEnableParameters(parsedArgs.KernelEvents, parsedArgs.KernelEvents);
546546
PerfViewLogger.Log.SessionParameters(s_UserModeSessionName, userFileName ?? "",
@@ -1109,7 +1109,7 @@ public void Stop(CommandLineArgs parsedArgs)
11091109

11101110
}
11111111

1112-
LogFile.WriteLine("Stopping tracing for sessions '" + KernelTraceEventParser.KernelSessionName +
1112+
LogFile.WriteLine("Stopping tracing for sessions '" + s_KernelessionName +
11131113
"' and '" + s_UserModeSessionName + "'.");
11141114

11151115
PerfViewLogger.Log.CommandLineParameters(ParsedArgsAsString(null, parsedArgs), Environment.CurrentDirectory, AppLog.VersionNumber);
@@ -1135,70 +1135,91 @@ public void Stop(CommandLineArgs parsedArgs)
11351135
}
11361136

11371137
// Try to stop the kernel session
1138-
try
1138+
1139+
Task stopKernel = Task.Factory.StartNew(delegate ()
11391140
{
1140-
if (parsedArgs.KernelEvents != KernelTraceEventParser.Keywords.None)
1141+
try
11411142
{
1142-
using (var kernelSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName, TraceEventSessionOptions.Attach))
1143+
if (parsedArgs.KernelEvents != KernelTraceEventParser.Keywords.None)
11431144
{
1144-
if (parsedArgs.InMemoryCircularBuffer)
1145+
using (var kernelSession = new TraceEventSession(s_KernelessionName, TraceEventSessionOptions.Attach))
11451146
{
1146-
kernelSession.SetFileName(Path.ChangeExtension(parsedArgs.DataFile, ".kernel.etl")); // Flush the file
1147-
1148-
// We need to manually do a kernel rundown to get the list of running processes and images loaded into memory
1149-
// Ideally this is done by the SetFileName API so we can avoid merging.
1150-
var rundownFile = Path.ChangeExtension(parsedArgs.DataFile, ".kernelRundown.etl");
1151-
1152-
// Note that enabling providers is async, and thus there is a concern that we would lose events if we don't wait
1153-
// until the events are logged before shutting down the session. However we only need the DCEnd events and
1154-
// those are PART of kernel session stop, which is synchronous (the session will not die until it is complete)
1155-
// so we don't have to wait after enabling the kernel session. It is somewhat unfortunate that we have both
1156-
// the DCStart and the DCStop events, but there does not seem to be a way of asking for just one set.
1157-
using (var kernelRundownSession = new TraceEventSession(s_UserModeSessionName + "Rundown", rundownFile))
1147+
if (parsedArgs.InMemoryCircularBuffer)
11581148
{
1159-
kernelRundownSession.BufferSizeMB = 256; // Try to avoid lost events.
1160-
kernelRundownSession.EnableKernelProvider(KernelTraceEventParser.Keywords.Process | KernelTraceEventParser.Keywords.ImageLoad);
1149+
LogFile.WriteLine("InMemoryCircularBuffer Set, Dumping kernel log");
1150+
kernelSession.SetFileName(Path.ChangeExtension(parsedArgs.DataFile, ".kernel.etl")); // Flush the file
1151+
1152+
1153+
LogFile.WriteLine("InMemoryCircularBuffer Set, Doing Kernel Rundown");
1154+
// We need to manually do a kernel rundown to get the list of running processes and images loaded into memory
1155+
// Ideally this is done by the SetFileName API so we can avoid merging.
1156+
var rundownFile = Path.ChangeExtension(parsedArgs.DataFile, ".kernelRundown.etl");
1157+
1158+
// Note that enabling providers is async, and thus there is a concern that we would lose events if we don't wait
1159+
// until the events are logged before shutting down the session. However we only need the DCEnd events and
1160+
// those are PART of kernel session stop, which is synchronous (the session will not die until it is complete)
1161+
// so we don't have to wait after enabling the kernel session. It is somewhat unfortunate that we have both
1162+
// the DCStart and the DCStop events, but there does not seem to be a way of asking for just one set.
1163+
using (var kernelRundownSession = new TraceEventSession(s_UserModeSessionName + "KernelRundown", rundownFile))
1164+
{
1165+
kernelRundownSession.BufferSizeMB = 256; // Try to avoid lost events.
1166+
kernelRundownSession.EnableKernelProvider(KernelTraceEventParser.Keywords.Process | KernelTraceEventParser.Keywords.ImageLoad);
1167+
}
1168+
LogFile.WriteLine("InMemoryCircularBuffer Set, Finished Kernel Rundown");
11611169
}
1170+
kernelSession.Stop();
11621171
}
1163-
kernelSession.Stop();
11641172
}
11651173
}
1166-
}
1167-
catch (FileNotFoundException) { LogFile.WriteLine("No Kernel events were active for this trace."); }
1168-
catch (Exception e) { if (!(e is ThreadInterruptedException)) { LogFile.WriteLine("Error stopping Kernel session: " + e.Message); } throw; }
1174+
catch (FileNotFoundException) { LogFile.WriteLine("No Kernel events were active for this trace."); }
1175+
catch (Exception e) { if (!(e is ThreadInterruptedException)) { LogFile.WriteLine("Error stopping Kernel session: " + e.Message); } throw; }
1176+
});
11691177

11701178
string dataFile = null;
1171-
try
1179+
Task stopUser = Task.Factory.StartNew(delegate ()
11721180
{
1173-
using (TraceEventSession clrSession = new TraceEventSession(s_UserModeSessionName, TraceEventSessionOptions.Attach))
1181+
try
11741182
{
1175-
if (parsedArgs.InMemoryCircularBuffer)
1183+
using (TraceEventSession clrSession = new TraceEventSession(s_UserModeSessionName, TraceEventSessionOptions.Attach))
11761184
{
1177-
dataFile = parsedArgs.DataFile;
1178-
clrSession.SetFileName(dataFile); // Flush the file
1179-
}
1180-
else
1181-
{
1182-
dataFile = clrSession.FileName;
1183-
}
1185+
if (parsedArgs.InMemoryCircularBuffer)
1186+
{
1187+
LogFile.WriteLine("InMemoryCircularBuffer Set, Dumping kernel log");
1188+
dataFile = parsedArgs.DataFile;
1189+
clrSession.SetFileName(dataFile); // Flush the file
1190+
}
1191+
else
1192+
{
1193+
dataFile = clrSession.FileName;
1194+
}
11841195

1185-
clrSession.Stop();
1196+
clrSession.Stop();
11861197

1187-
// Try to force the rundown of CLR method and loader events. This routine does not fail.
1188-
DoClrRundownForSession(dataFile, clrSession.SessionName, parsedArgs);
1198+
// Try to force the rundown of CLR method and loader events. This routine does not fail.
1199+
DoClrRundownForSession(dataFile, clrSession.SessionName, parsedArgs);
1200+
}
11891201
}
1190-
}
1191-
catch (Exception e) { if (!(e is ThreadInterruptedException)) { LogFile.WriteLine("Error stopping User session: " + e.Message); } throw; }
1202+
catch (Exception e) { if (!(e is ThreadInterruptedException)) { LogFile.WriteLine("Error stopping User session: " + e.Message); } throw; }
1203+
});
11921204

1193-
try
1205+
Task stopHeap = Task.Factory.StartNew(delegate ()
11941206
{
1195-
using (var heapSession = new TraceEventSession(s_HeapSessionName, TraceEventSessionOptions.Attach))
1207+
try
11961208
{
1197-
heapSession.Stop();
1209+
using (var heapSession = new TraceEventSession(s_HeapSessionName, TraceEventSessionOptions.Attach))
1210+
{
1211+
heapSession.Stop();
1212+
}
11981213
}
1199-
}
1200-
catch (FileNotFoundException) { LogFile.WriteLine("No Heap events were active for this trace."); }
1201-
catch (Exception e) { if (!(e is ThreadInterruptedException)) { LogFile.WriteLine("Error stopping Heap session: " + e.Message); } throw; }
1214+
catch (FileNotFoundException) { LogFile.WriteLine("No Heap events were active for this trace."); }
1215+
catch (Exception e) { if (!(e is ThreadInterruptedException)) { LogFile.WriteLine("Error stopping Heap session: " + e.Message); } throw; }
1216+
});
1217+
1218+
// We stop the two sessions concurrently because we have notice that sometime the kernel session
1219+
// Takes a while to shutdown, and we want the user mode session to shutdown at basically the same time
1220+
// Doing them concurrently minimizes any skew.
1221+
Task.WaitAll(stopKernel, stopUser, stopHeap);
1222+
LogFile.WriteLine("Done stopping sessions.");
12021223

12031224
UninstallETWClrProfiler(LogFile);
12041225

@@ -1268,10 +1289,10 @@ public void Abort(CommandLineArgs parsedArgs)
12681289

12691290
s_abortInProgress = true;
12701291
m_logFile.WriteLine("Aborting tracing for sessions '" +
1271-
KernelTraceEventParser.KernelSessionName + "' and '" + s_UserModeSessionName + "'.");
1292+
s_KernelessionName + "' and '" + s_UserModeSessionName + "'.");
12721293
try
12731294
{
1274-
using (var kernelSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName, TraceEventSessionOptions.Attach))
1295+
using (var kernelSession = new TraceEventSession(s_KernelessionName, TraceEventSessionOptions.Attach))
12751296
{
12761297
kernelSession.Stop(true);
12771298
}
@@ -3362,6 +3383,7 @@ private void WaitForRundownIdle(int minSeconds, int maxSeconds, string rundownFi
33623383
}
33633384

33643385
internal static string s_UserModeSessionName = "PerfViewSession";
3386+
internal static string s_KernelessionName = KernelTraceEventParser.KernelSessionName;
33653387
private static string s_HeapSessionName { get { return s_UserModeSessionName + "Heap"; } }
33663388

33673389
private static bool s_addedSupportDirToPath;
@@ -3675,9 +3697,7 @@ private static void ParseProviderSpec(string providerSpec, TraceEventLevel level
36753697
providerGuid = TraceEventProviders.GetProviderGuidByName(providerSpec);
36763698
// Look it up by name
36773699
if (providerGuid == Guid.Empty)
3678-
{
3679-
throw new ApplicationException("Could not find provider name '" + providerSpec + "'");
3680-
}
3700+
TraceEventProviders.GetEventSourceGuidFromName(providerSpec);
36813701
}
36823702

36833703
retList.Add(new ParsedProvider()

src/PerfView/PerfView.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,13 @@
216216
<Link>amd64\EtwClrProfiler.dll</Link>
217217
<Visible>False</Visible>
218218
</EmbeddedResource>
219-
<!--<EmbeddedResource Include="$(OutDir)\PerfView.xml">
219+
<EmbeddedResource Include="SupportFiles\PerfView.xml">
220220
<Type>Non-Resx</Type>
221221
<WithCulture>false</WithCulture>
222222
<LogicalName>.\PerfView.xml</LogicalName>
223-
<SubType>Designer</SubType>
223+
<Link>PerfView.xml</Link>
224224
<Visible>False</Visible>
225-
</EmbeddedResource>-->
225+
</EmbeddedResource>
226226
<EmbeddedResource Include="..\TraceEvent\$(OutDir)Microsoft.Diagnostics.Tracing.TraceEvent.dll">
227227
<Type>Non-Resx</Type>
228228
<WithCulture>false</WithCulture>

0 commit comments

Comments
 (0)