using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Parsers;
using System;
using System.Collections.Generic;
using Utilities;
namespace PerfView
{
///
/// The code:PerfViewCommandLine class holds the parsed form of all the commandLine line arguments. It is
/// initialized by handing it the 'args' array for main, and it has a public field for each named argument
/// (eg -debug). See code:#CommandLineDefinitions for the code that defines the arguments (and the help
/// strings associated with them).
///
/// See code:CommandLineParser for more on parser itself.
///
public class CommandLineArgs
{
public CommandLineArgs()
{
}
///
/// Sets CommandLineFailure field if there is a parse failure
///
public void ParseArgs(string[] args)
{
try
{
var parser = new CommandLineParser(args);
SetupCommandLine(parser);
if (parser.HelpRequested != null)
{
HelpRequested = true;
}
if (CommandAndArgs != null)
{
CommandLine = CommandLineUtilities.FormCommandLineFromArguments(CommandAndArgs, 0);
}
parser.CompleteValidation();
}
catch (CommandLineParserException e)
{
CommandLineFailure = e;
}
}
public static string GetHelpString(int maxLineWidth)
{
string ret;
var commandLineArgs = new CommandLineArgs(maxLineWidth, out ret);
return ret;
}
public bool HelpRequested;
public bool AcceptEULA;
public bool TrustPdbs;
public bool SafeMode;
public string RestartingToElevelate; // internal: are we restarting perfView so we can elevate. The value is the old command
// The command to execute (determined by the parameter set)
public Action DoCommand;
// options common to multiple commands
public string DataFile; // This is the name of the ETL file (not the ZIP file)
public string LogFile;
// Memory options
public string ProcessDumpFile; // if taking a snapshot from a dump, this is the dump file (dataFile is the output file)
public bool SaveETL; // Save the ETL file when dumping the JS heap
public bool DumpData; // Dump the heap data as well as the connectivity info
public bool Freeze; // Freeze the process while the dump is taken
public int MaxDumpCountK = 250; // Maximum size of the File to generate. We sample aggressively enough to try to hit this count of objects in the file
public int MaxNodeCountK; // Maximum size to even look at in the heap
#if CROSS_GENERATION_LIVENESS
// Cross generation liveness options
public int CGL_PID;
public int CGL_Generation;
public ulong CGL_PromotedBytesThreshold;
public string CGL_PathToOutputFile;
#endif
// view options
public string Process; // A process name to focus on.
// run Options
public string[] CommandAndArgs; // This is broken up into words
public string CommandLine; // This is a one long string.
// collect options
public int MaxCollectSec; // collect no more than this number of seconds.
public string[] StopOnPerfCounter; // stop collection on this performance counter trigger.
public string[] StartOnPerfCounter; // start collection on this performance counter trigger.
public bool StopOnGen2GC; // Stop on a gen 2 GC
public string[] StopOnEtwEvent;
public string StopOnException;
public int StopOnGCOverMsec;
public int StopOnBGCFinalPauseOverMsec; // Stop on a BGC whose final pause is over this many ms
public float DecayToZeroHours; //causes 'StopOn*OverMSec' timeouts to decay to zero over this time period
public int MinSecForTrigger = 3; // affects StopOnPerfCounter and StartOnPerfCounter
public string StopOnEventLogMessage; // stop collection on event logs
public string StopCommand; // is executed when a stop is triggered.
public int StopOnAppFabricOverMsec;
public int DelayAfterTriggerSec = 5; // Number of seconds to wait after a trigger
public string[] MonitorPerfCounter; // logs perf counters to the ETL file.
// Start options.
public bool StackCompression = true; // Use compresses stacks when collecting traces.
public int BufferSizeMB = 256;
public int CircularMB;
public bool InMemoryCircularBuffer; // Uses EVENT_TRACE_BUFFERING_MODE for an in-memory circular buffer
public KernelTraceEventParser.Keywords KernelEvents = KernelTraceEventParser.Keywords.Default;
public string[] CpuCounters; // Specifies any profile sources (CPU counters) to turn on (Win 8 only)
public ClrTraceEventParser.Keywords ClrEvents = ClrTraceEventParser.Keywords.Default;
public TraceEventLevel ClrEventLevel = Microsoft.Diagnostics.Tracing.TraceEventLevel.Verbose; // The verbosity of CLR events
public TplEtwProviderTraceEventParser.Keywords TplEvents = TplEtwProviderTraceEventParser.Keywords.Default;
public bool ThreadTime; // Shortcut for /KernelEvents=ThreadTime
public bool GCOnly; // collect only enough for GC analysis
public bool GCCollectOnly; // Turn off even the allocation Tick
public bool DotNetAlloc; // Turn on .NET Allocation profiling
public bool DotNetAllocSampled; // Turn on .NET Allocation profiling, but only sampled (in a smart way)
public bool DotNetCalls; // Turn on logging of every .NET call
public bool DotNetCallsSampled; // Sampling of .NET calls.
public bool DisableInlining; // Force inlining to be disabled. (useful for DotNetCalls).
public bool JITInlining; // Turn on logging of successful and failed JIT inlining
public int OSHeapProcess; // Turn on OS Heap tracing for the process with the given process ID.
public string OSHeapExe; // Turn on OS heap tracing for any process with the given EXE
public bool NetworkCapture; // Capture the full packets of every incoming and outgoing packet
public bool NetMonCapture; // Capture a NetMon-only trace as well as a standard ETW trace (implies NetworkCapture)
public bool CCWRefCount; // Capture CCW references count increasing and decreasing
public bool RuntimeLoading; // Capture information about runtime loading such as R2R and type load events
public bool Wpr; // Collect like WPR (no zip, puts NGEN pdbs in a .ngenpdbs directory).
public string[] Providers; // Additional providers to turn on.
// Stop options.
public string FocusProcess; // The target process for CLR Rundown.
public bool NoRundown;
public bool NoNGenPdbs;
public bool NoNGenRundown;
public bool NoClrRundown;
public bool NoV2Rundown;
public bool LowPriority;
public bool? Merge;
public bool? Zip;
public bool ShouldMerge
{
get
{
// We must merge if we Zip.
if (ShouldZip)
{
return true;
}
// User asks for it explicitly.
if (Merge.HasValue)
{
return Merge.Value;
}
// Otherwise the default is to merge.
return true;
}
}
public bool ShouldZip
{
get
{
// User asks for it explicitly.
if (Zip.HasValue)
{
return Zip.Value;
}
// If user asks for no-merge explicitly, and Zip was was not asked for, then /Zip:false is assumed
if (Merge.HasValue && Merge.Value == false)
{
return false;
}
// by default, we don't zip if we were asked to mimic WPR.
if (Wpr)
{
return false;
}
// But the final default is true.
return true;
}
}
public int RundownTimeout = 120;
public int MinRundownTime;
public bool NoView;
public float CpuSampleMSec = 1.0F;
public bool KeepAllEvents;
public int MaxEventCount;
public bool ContinueOnError;
public double SkipMSec;
public DateTime StartTime;
public DateTime EndTime;
public bool ForceNgenRundown;
public bool DumpHeap;
// Collect options
public bool NoGui;
public int CollectMultiple; // Collect several instances (incrementing the file name)
// Mark options
public string Message;
// Viewer options
public bool UnsafePDBMatch;
public bool ShowUnknownAddresses;
public bool ShowOptimizationTiers;
// Parameter to CreateExtensionTemplate
public string ExtensionName = "Global";
// If parsing fails, this field is set.
public CommandLineParserException CommandLineFailure;
#region private
private CommandLineArgs(int maxLineWidth, out string helpString)
: this()
{
var parser = new CommandLineParser("perfView /?");
SetupCommandLine(parser);
helpString = parser.GetHelp(maxLineWidth, null);
}
///
/// Shared logic to configure CommandLineArgs for GCCollectOnly mode
///
///
internal static void ConfigureForGCCollectOnly(CommandLineArgs commandLineArgs)
{
// The process events are so we get process names. The ImageLoad events are so that we get version information about the DLLs.
commandLineArgs.KernelEvents = KernelTraceEventParser.Keywords.Process | KernelTraceEventParser.Keywords.ImageLoad;
commandLineArgs.ClrEvents = ClrTraceEventParser.Keywords.GC;
commandLineArgs.ClrEventLevel = TraceEventLevel.Informational;
commandLineArgs.TplEvents = TplEtwProviderTraceEventParser.Keywords.None;
commandLineArgs.NoRundown = true;
}
private void SetupCommandLine(CommandLineParser parser)
{
// #CommandLineDefinitions
parser.ParameterSetsWhereQualifiersMustBeFirst = new string[] { "run", "UserCommand" };
parser.NoDashOnParameterSets = true;
parser.DefineOptionalQualifier("LogFile", ref LogFile, "Send messages to this file instead launching the GUI. Intended for batch scripts and other automation.");
// These apply to start, collect and run
parser.DefineOptionalQualifier("BufferSize", ref BufferSizeMB, "The size the buffers (in MB) the OS should use to store events waiting to be written to disk."); // TODO remove eventually.
parser.DefineOptionalQualifier("Circular", ref CircularMB, "Do Circular logging with a file size in MB. Zero means non-circular."); // TODO remove eventually.
parser.DefineOptionalQualifier("BufferSizeMB", ref BufferSizeMB, "The size the buffers (in MB) the OS should use to store events waiting to be written to disk.");
parser.DefineOptionalQualifier("CircularMB", ref CircularMB, "Do Circular logging with a file size in MB. Zero means non-circular.");
parser.DefineOptionalQualifier("InMemoryCircularBuffer", ref InMemoryCircularBuffer, "Keeps the circular buffer in memory until the session is stopped.");
parser.DefineOptionalQualifier("StackCompression", ref StackCompression, "Use stack compression (only on Win 8+) to make collected file smaller.");
parser.DefineOptionalQualifier("MaxCollectSec", ref MaxCollectSec,
"Turn off collection (and kill the program if perfView started it) after this many seconds. Zero means no timeout.");
parser.DefineOptionalQualifier("StopOnPerfCounter", ref StopOnPerfCounter,
"This is of the form CATEGORY:COUNTERNAME:INSTANCE OP NUM where CATEGORY:COUNTERNAME:INSTANCE, identify " +
"a performance counter (same as PerfMon), OP is either < or >, and NUM is a number. " +
"When that condition is true then collection will stop. You can specify this qualifier more than once (logical OR). See 'Stop Trigger' in the users guide for more.");
parser.DefineOptionalQualifier("StopOnEventLogMessage", ref StopOnEventLogMessage,
"Stop when an event log message that matches the given (ignore case) regular expression is written to the Windows 'Application' event log. " +
"You can specify a particular event log with the syntax eventLogName@RegExp. Can be specified more than once (logical OR).");
parser.DefineOptionalQualifier("StopOnEtwEvent", ref StopOnEtwEvent,
"This is of the form PROVIDER/EVENTNAME;key1=value1;key2=value2... " +
"This option is quite powerful, See the users guide for more details.");
int StopOnRequestOverMsec = 0;
int StopOnGCSuspendOverMSec = 0;
// These are basically special cases of the /StopOnEtwEvent
parser.DefineOptionalQualifier("StopOnRequestOverMsec", ref StopOnRequestOverMsec,
"Trigger a stop of a collect command if there is any IIS request that is longer than the given number of MSec.");
parser.DefineOptionalQualifier("StopOnGCOverMsec", ref StopOnGCOverMsec,
"Trigger a stop of a collect command if there is a .NET Garbage Collection (GC) is longer than the given number of MSec.");
parser.DefineOptionalQualifier("StopOnGCSuspendOverMSec", ref StopOnGCSuspendOverMSec,
"Trigger a stop of a collect command if there is a .NET Garbage Collection (GC) where suspending for the GC took over the given number of MSec.");
parser.DefineOptionalQualifier("StopOnBGCFinalPauseOverMsec", ref StopOnBGCFinalPauseOverMsec,
"Trigger a stop of a collect command if there is a background .NET Garbage Collection (GC) whose final pause is longer than the given number of MSec. To work correctly, " +
"this requires that heap survival and movement tracking is not enabled.");
parser.DefineOptionalQualifier("StopOnAppFabricOverMsec", ref StopOnAppFabricOverMsec,
"Trigger a stop of a collect command if there is a AppFabric request is longer than the given number of MSec.");
parser.DefineOptionalQualifier("StopOnException", ref StopOnException,
"Where the text is a regular expression that will be used to match the full name and message of the .NET Exception thrown." +
"The empty string represents any exception.");
parser.DefineOptionalQualifier("StopOnGen2GC", ref StopOnGen2GC,
"This will stop on any non-background Gen2 GC from the given process (can be a process ID or a process Name (exe file name without path or extension) or * (any process)");
parser.DefineOptionalQualifier("Process", ref Process, "A process name (exe file name without directory or extension) or the Decimal Process ID. " +
"If used with the /StopOn* qualifiers using ETW events, will restrict events to only that process.");
parser.DefineOptionalQualifier("DecayToZeroHours", ref DecayToZeroHours,
"The trigger value used in StopOnPerfCounter or StopOn*OverMSec will decay to zero in this interval of time.");
parser.DefineOptionalQualifier("MinSecForTrigger", ref MinSecForTrigger,
"The number of seconds a perf Counter has to be above threshold before it is considered triggered.");
parser.DefineOptionalQualifier("DelayAfterTriggerSec", ref DelayAfterTriggerSec,
"Wait this number of seconds after a trigger before actually stopping the trace.");
parser.DefineOptionalQualifier("CollectMultiple", ref CollectMultiple, "Collect Multiple instance (used in conjunction with StopTrigger).");
parser.DefineOptionalQualifier("StartOnPerfCounter", ref StartOnPerfCounter,
"This is of the form CATEGORY:COUNTERNAME:INSTANCE OP NUM where CATEGORY:COUNTERNAME:INSTANCE, identify " +
"a performance counter (same as PerfMon), OP is either < or >, and NUM is a number. " +
"When that condition is true then collection will start. You can specify this qualifier more than once. Search for 'MonitorPerfCounter' in the users guide for more.");
parser.DefineOptionalQualifier("StopCommand", ref StopCommand,
"If present this command is executed when a PerfView stops. It is useful to stopping other tracing logic external to PerfView.");
List etwStopEvents = new List();
if (StopOnRequestOverMsec != 0)
{
etwStopEvents.Add("Microsoft-Windows-IIS/EventID(1);Level=Critical;TriggerMSec=" + StopOnRequestOverMsec);
}
if (StopOnGCSuspendOverMSec != 0)
{
etwStopEvents.Add("E13C0D23-CCBC-4E12-931B-D9CC2EEE27E4/GC/SuspendEEStart;StopEvent=GC/SuspendEEStop;StartStopID=ThreadID;Keywords=0x1;TriggerMSec=" + StopOnGCSuspendOverMSec);
}
if (0 < etwStopEvents.Count)
{
if (StopOnEtwEvent != null)
{
etwStopEvents.AddRange(StopOnEtwEvent);
}
StopOnEtwEvent = etwStopEvents.ToArray();
}
// Respect the /Process and /DecayToZeroHours options by tacking them on the end if they are not already present.
if (StopOnEtwEvent != null && (Process != null || DecayToZeroHours != 0))
{
etwStopEvents.Clear();
foreach (var stopEtwEvent in StopOnEtwEvent)
{
var newStopEtwEvent = stopEtwEvent;
if (Process != null && !stopEtwEvent.Contains(";Process="))
{
newStopEtwEvent += ";Process=" + Process;
}
if (DecayToZeroHours != 0 && !stopEtwEvent.Contains(";DecayToZeroHours="))
{
newStopEtwEvent += ";DecayToZeroHours=" + DecayToZeroHours;
}
etwStopEvents.Add(newStopEtwEvent);
}
StopOnEtwEvent = etwStopEvents.ToArray();
}
parser.DefineOptionalQualifier("MonitorPerfCounter", ref MonitorPerfCounter,
"This is of the form CATEGORY:COUNTERNAME:INSTANCE@NUM where CATEGORY:COUNTERNAME:INSTANCE, identify " +
"a performance counter (same as PerfMon), and NUM is a number representing seconds. The @NUM part is " +
"optional and defaults to 2. The value of the performance counter is logged to the ETL file as an " +
"event ever NUM seconds");
parser.DefineOptionalQualifier("CpuSampleMSec", ref CpuSampleMSec,
"The interval (MSec) between CPU samples (.125Msec min).");
// These apply to Stop Collect and Run
parser.DefineOptionalQualifier("Merge", ref Merge, "Do a merge after stopping collection.");
parser.DefineOptionalQualifier("Zip", ref Zip, "Zip the ETL file (implies /Merge).");
parser.DefineOptionalQualifier("Wpr", ref Wpr, "Make output mimic WPR (Windows Performance Recorder). Don't ZIP, make a .ngenpdbs directory. " +
"This also enables threadTime as well as user mode providers WPR would normally collect by default. This option can also be used " +
"On the unzip command. See 'Working with WPA' in the help for more.");
parser.DefineOptionalQualifier("LowPriority", ref LowPriority, "Do merging and ZIPing at low priority to minimize impact to system.");
parser.DefineOptionalQualifier("NoRundown", ref NoRundown, "Don't collect rundown events. Use only if you know the process of interest has exited.");
parser.DefineOptionalQualifier("FocusProcess", ref FocusProcess, "Either a decimal process ID or a process name (exe name without path but WITH extension) to focus ETW commands." +
"All NON-KERNEL providers are only send to this process (and rundown is only done on this process) which can cut overhead significantly in some cases.");
parser.DefineOptionalQualifier("NoNGenPdbs", ref NoNGenPdbs, "Don't generate NGEN Pdbs");
parser.DefineOptionalQualifier("NoNGenRundown", ref NoNGenRundown,
"Don't do rundown of symbolic information in NGEN images (only needed pre V4.5).");
parser.DefineOptionalQualifier("NoClrRundown", ref NoClrRundown,
"Don't do rundown .NET (CLR) rundown information )(for symbolic name lookup).");
parser.DefineOptionalQualifier("RundownTimeout", ref RundownTimeout,
"Maximum number of seconds to wait for CLR rundown to complete.");
parser.DefineOptionalQualifier("MinRundownTime", ref MinRundownTime,
"Minimum number of seconds to wait for CLR rundown to complete.");
parser.DefineOptionalQualifier("KeepAllEvents", ref KeepAllEvents,
"A debug option to keep all events, even symbolic rundown events.");
parser.DefineOptionalQualifier("MaxEventCount", ref MaxEventCount, "Limits the total number of events. " +
"Useful for trimming large ETL files. 1M typically yields 300-400 Meg of data considered.");
parser.DefineOptionalQualifier("SkipMSec", ref SkipMSec, "Skips the first N MSec of the trace. " +
"Useful for trimming large ETL files in conjunction with the /MaxEventCount qualifier.");
parser.DefineOptionalQualifier("StartTime", ref StartTime, "The start date and time used to filter events of the input trace for formats that support this.");
parser.DefineOptionalQualifier("EndTime", ref EndTime, "The end date and time used to filter events of the input trace for formats that support this.");
parser.DefineOptionalQualifier("ContinueOnError", ref ContinueOnError, "Processes bad traces as best it can.");
parser.DefineOptionalQualifier("CpuCounters", ref CpuCounters,
"A comma separated list of hardware CPU counters specifications NAME:COUNT to turn on. " +
"See Users guide for details. See ListCpuCounters for available sources (Win8 only)");
parser.DefineOptionalQualifier("Providers", ref Providers,
"Additional providers. This is comma separated list of ProviderGuid:Keywords:Level:Stack specs. " +
"This qualifier has the same syntax as the Additional Providers TextBox in the collection window. " +
" See help on that for more.");
string[] onlyProviders = null;
parser.DefineOptionalQualifier("OnlyProviders", ref onlyProviders,
"Like the Providers qualifier, but also turns off the default Kernel and CLR providers.");
if (onlyProviders != null)
{
// Allow stack traces to work if 'stacks' was specified.
bool hasStacks = false;
bool hasTpl = false;
foreach (var provider in onlyProviders)
{
if (0 <= provider.IndexOf("@StacksEnabled=true", StringComparison.OrdinalIgnoreCase))
{
hasStacks = true;
}
if (0 <= provider.IndexOf("@EventIDStacksToEnable", StringComparison.OrdinalIgnoreCase))
{
hasStacks = true;
}
if (provider.StartsWith(".NETTasks", StringComparison.OrdinalIgnoreCase))
{
hasTpl = true;
}
}
if (hasStacks)
{
KernelEvents = KernelTraceEventParser.Keywords.Process | KernelTraceEventParser.Keywords.Thread | KernelTraceEventParser.Keywords.ImageLoad;
ClrEvents = ClrTraceEventParser.Keywords.Jit | ClrTraceEventParser.Keywords.Loader;
}
else
{
KernelEvents = KernelTraceEventParser.Keywords.None;
ClrEvents = ClrTraceEventParser.Keywords.None;
NoNGenRundown = true; // We still do normal rundown because EventSource rundown is done there.
NoClrRundown = true;
}
if (!hasTpl)
{
// Turn on causality tracking.
TplEvents = TplEtwProviderTraceEventParser.Keywords.TasksFlowActivityIds;
}
Providers = onlyProviders;
}
parser.DefineOptionalQualifier("ThreadTime", ref ThreadTime, "Shortcut for turning on context switch and readyThread events");
if (ThreadTime)
{
KernelEvents = KernelTraceEventParser.Keywords.ThreadTime;
}
parser.DefineOptionalQualifier("GCOnly", ref GCOnly, "Turns on JUST GC collections an allocation sampling.");
if (GCOnly)
{
// TODO this logic is cloned. We need it in only one place. If you update it do the other location as well
// For stack parsing.
KernelEvents = KernelTraceEventParser.Keywords.Process | KernelTraceEventParser.Keywords.Thread | KernelTraceEventParser.Keywords.ImageLoad | KernelTraceEventParser.Keywords.VirtualAlloc;
ClrEvents = ClrTraceEventParser.Keywords.GC | ClrTraceEventParser.Keywords.GCHeapSurvivalAndMovement | ClrTraceEventParser.Keywords.Stack |
ClrTraceEventParser.Keywords.Jit | ClrTraceEventParser.Keywords.StopEnumeration | ClrTraceEventParser.Keywords.SupressNGen |
ClrTraceEventParser.Keywords.Loader | ClrTraceEventParser.Keywords.Exception | ClrTraceEventParser.Keywords.Type | ClrTraceEventParser.Keywords.GCHeapAndTypeNames;
TplEvents = TplEtwProviderTraceEventParser.Keywords.None;
// This is not quite correct if you have providers of your own, but this covers the most important case.
if (Providers == null)
{
Providers = new string[] { "Microsoft-Windows-Kernel-Memory:0x60" };
}
CommandProcessor.s_UserModeSessionName = "PerfViewGCSession";
DataFile = "PerfViewGCOnly.etl";
}
parser.DefineOptionalQualifier("GCCollectOnly", ref GCCollectOnly, "Turns on GC collections (no allocation sampling).");
if (GCCollectOnly)
{
ConfigureForGCCollectOnly(this);
CommandProcessor.s_UserModeSessionName = "PerfViewGCSession";
DataFile = "PerfViewGCCollectOnly.etl";
}
// WPR option implies a bunch of kernel events.
if (Wpr)
{
KernelEvents = KernelTraceEventParser.Keywords.ThreadTime |
KernelTraceEventParser.Keywords.DeferedProcedureCalls |
KernelTraceEventParser.Keywords.Driver |
KernelTraceEventParser.Keywords.Interrupt;
}
parser.DefineOptionalQualifier("DumpHeap", ref DumpHeap, "Capture a heap snapshot on profile stop");
parser.DefineOptionalQualifier("ClrEventLevel", ref ClrEventLevel, "The verbosity for CLR events");
parser.DefineOptionalQualifier("ClrEvents", ref ClrEvents,
"A comma separated list of .NET CLR events to turn on. See Users guide for details.");
parser.DefineOptionalQualifier("KernelEvents", ref KernelEvents,
"A comma separated list of windows OS kernel events to turn on. See Users guide for details.");
parser.DefineOptionalQualifier("TplEvents", ref TplEvents,
"A comma separated list of Task Parallel Library (TPL) events to turn on. See Users guide for details.");
parser.DefineOptionalQualifier("DotNetAlloc", ref DotNetAlloc, "Turns on per-allocation .NET profiling.");
parser.DefineOptionalQualifier("DotNetAllocSampled", ref DotNetAllocSampled, "Turns on per-allocation .NET profiling, sampling types in a smart way to keep overhead low.");
parser.DefineOptionalQualifier("DotNetCalls", ref DotNetCalls, "Turns on per-call .NET profiling.");
parser.DefineOptionalQualifier("DotNetCallsSampled", ref DotNetCallsSampled, "Turns on per-call .NET profiling, sampling types in a smart way to keep overhead low.");
parser.DefineOptionalQualifier("DisableInlining", ref DisableInlining, "Turns off inlining (but only affects processes that start after trace start.");
parser.DefineOptionalQualifier("JITInlining", ref JITInlining, "Turns on logging of successful and failed JIT inlining attempts.");
parser.DefineOptionalQualifier("CCWRefCount", ref CCWRefCount, "Turns on logging of information about .NET Native CCW reference counting.");
parser.DefineOptionalQualifier("RuntimeLoading", ref RuntimeLoading, "Turn on logging of runtime loading operations.");
parser.DefineOptionalQualifier("OSHeapProcess", ref OSHeapProcess, "Turn on per-allocation profiling of allocation from the OS heap for the process with the given process ID.");
parser.DefineOptionalQualifier("OSHeapExe", ref OSHeapExe, "Turn on per-allocation profiling of allocation from the OS heap for the process with the given EXE (only filename WITH extension).");
parser.DefineOptionalQualifier("NetworkCapture", ref NetworkCapture, "Captures the full data of every network packet entering or leaving the OS.");
parser.DefineOptionalQualifier("NetMonCapture", ref NetMonCapture, "Create _netmon.etl file that NetMon.exe can read, along with the standard ETL file. Implies /NetworkCapture.");
parser.DefineOptionalQualifier("ForceNgenRundown", ref ForceNgenRundown,
"By default on a V4.0 runtime NGEN rundown is suppressed, because NGEN PDB are a less expensive way of getting symbolic " +
"information for NGEN images. This option forces NGEN rundown, so NGEN PDBs are not needed. This can be useful " +
"in some scenarios where NGEN PDB are not working properly.");
parser.DefineOptionalQualifier("NoV2Rundown", ref NoV2Rundown,
"Don't do rundown for .NET (CLR) V2 processes.");
parser.DefineOptionalQualifier("TrustPdbs", ref TrustPdbs, "Normally PerfView does not trust PDBs outside the _NT_SYMBOL_PATH and pops a dialog box. Suppress this.");
parser.DefineOptionalQualifier("AcceptEULA", ref AcceptEULA, "Accepts the EULA associated with PerfView.");
parser.DefineOptionalQualifier("DataFile", ref DataFile,
"FileName of the profile data to generate.");
parser.DefineOptionalQualifier("NoView", ref NoView,
"Normally after collecting data the data is viewed. This suppresses that.");
parser.DefineOptionalQualifier("UnsafePDBMatch", ref UnsafePDBMatch,
"Allow the use of PDBs even when the trace does not contain PDB signatures.");
parser.DefineOptionalQualifier("ShowUnknownAddresses", ref ShowUnknownAddresses,
"Displays the hexadecimal address rather than ? when the address is unknown.");
parser.DefineOptionalQualifier("ShowOptimizationTiers", ref ShowOptimizationTiers,
"Displays the optimization tier of each code version executed for the method.");
parser.DefineOptionalQualifier("NoGui", ref NoGui,
"Use the Command line version of the command (like on ARM). Brings up a console window. For batch scripts/automation use /LogFile instead (see users guide under 'Scripting' for more).");
parser.DefineOptionalQualifier("SafeMode", ref SafeMode, "Turn off parallelism and other risky features.");
parser.DefineOptionalQualifier("RestartingToElevelate", ref RestartingToElevelate, "Internal: indicates that perfView is restarting to get Admin privileges.");
string sessionName = null;
parser.DefineOptionalQualifier("SessionName", ref sessionName, "Define the name for the user mode session (kernel session will also be named analogously) Useful for collecting traces when another ETW profiler (including PerfView) is being used.");
if (sessionName != null)
{
if (Environment.OSVersion.Version.Major * 10 + Environment.OSVersion.Version.Minor < 62)
throw new ApplicationException("SessionName qualifier only works on Windows 8 and above.");
CommandProcessor.s_UserModeSessionName = sessionName;
CommandProcessor.s_KernelessionName = sessionName + "Kernel";
}
parser.DefineOptionalQualifier("MaxNodeCountK", ref MaxNodeCountK,
"The maximum number of objects (in K or thousands) that will even be examined when dumping the heap. Avoids memory use at collection time. " +
"This is useful if heap dumping causes out of memory exceptions.");
/* end of qualifier that apply to more than one parameter set (command) */
/****************************************************************************************/
/* Parameter set (command) definitions */
parser.DefineParameterSet("run", ref DoCommand, App.CommandProcessor.Run,
"Starts data collection, runs a command and stops.");
parser.DefineParameter("CommandAndArgs", ref CommandAndArgs,
"Command to run and arguments (PerfView options must come before run command).");
parser.DefineParameterSet("collect", ref DoCommand, App.CommandProcessor.Collect,
"Starts data collection, wait for user input, then stops.");
parser.DefineOptionalParameter("DataFile", ref DataFile,
"ETL file containing profile data.");
parser.DefineParameterSet("start", ref DoCommand, App.CommandProcessor.Start,
"Starts machine wide profile data collection.");
parser.DefineOptionalParameter("DataFile", ref DataFile, "ETL file containing profile data.");
parser.DefineParameterSet("stop", ref DoCommand, App.CommandProcessor.Stop,
"Stop collecting profile data (machine wide). If you specified EventSources with the /Providers qualifier on start you should repeat them here to insure manifest rundown.");
parser.DefineParameterSet("mark", ref DoCommand, App.CommandProcessor.Mark,
"Add a PerfView 'Mark' event to the event stream with a optional string message");
parser.DefineOptionalParameter("Message", ref Message, "The string message to attach to the PerfView Mark event.");
parser.DefineParameterSet("abort", ref DoCommand, App.CommandProcessor.Abort,
"Insures that any active PerfView sessions are stopped.");
parser.DefineParameterSet("merge", ref DoCommand, App.CommandProcessor.Merge,
"Combine separate ETL files into a single ETL file (that can be decoded on another machine).");
parser.DefineOptionalParameter("DataFile", ref DataFile, "ETL file containing profile data.");
parser.DefineParameterSet("unzip", ref DoCommand, App.CommandProcessor.Unzip,
"Unpack a ZIP file into its ETL file (and possibly its NGEN PDBS) /WPR option can be specified.");
parser.DefineOptionalParameter("DataFile", ref DataFile, "ETL file containing profile data.");
parser.DefineParameterSet("listSessions", ref DoCommand, App.CommandProcessor.ListSessions,
"Lists active ETW sessions.");
parser.DefineParameterSet("ListCpuCounters", ref DoCommand, App.CommandProcessor.ListCpuCounters,
"Lists the ListCpuCounters CPU counters available on the system (win8+ only).");
parser.DefineParameterSet("EnableKernelStacks", ref DoCommand, App.CommandProcessor.EnableKernelStacks,
"On X64 machines if you have problems with broken stacks when the code is executing in the kernel," +
" setting this option and rebooting may improve things");
parser.DefineParameterSet("DisableKernelStacks", ref DoCommand, App.CommandProcessor.DisableKernelStacks,
"Resets the registry keys set by EnableKernelStack.");
string ProcessParam = null;
parser.DefineParameterSet("HeapSnapshot", ref DoCommand, App.CommandProcessor.HeapSnapshot,
"Take a snapshot of the CLR GC heap of a process.");
parser.DefineParameter("Process", ref ProcessParam, "The process ID or Process Name (Exe without extension) of the process take a heap snapshot.");
parser.DefineOptionalParameter("DataFile", ref DataFile, "The name of the file to place the heap snapshot.");
parser.DefineOptionalQualifier("SaveETL", ref SaveETL, "Save an ETL file along with the GCDump file when dumping the JS Heap.");
parser.DefineOptionalQualifier("MaxDumpCountK", ref MaxDumpCountK,
"The maximum number of objects (in K or thousands) to place int the .gcDump file. Sample sufficiently to hit this metric.");
parser.DefineOptionalQualifier("Freeze", ref Freeze, "Freeze the dump while data is taken.");
parser.DefineParameterSet("ForceGC", ref DoCommand, App.CommandProcessor.ForceGC,
"Forces a GC on the specified process");
parser.DefineParameter("Process", ref ProcessParam, "The process ID or Process Name (Exe without extension) of the process to force a GC.");
// We have both a qualifier and a parameter named Process. It is OK that they use the same variable, but the parameter should not
// overwrite the qualifier if it is null.
if (ProcessParam != null)
{
Process = ProcessParam;
}
parser.DefineParameterSet("HeapSnapshotFromProcessDump", ref DoCommand, App.CommandProcessor.HeapSnapshotFromProcessDump,
"Extract the CLR GC heap from a process dump file specified.");
parser.DefineParameter("ProcessDumpFile", ref ProcessDumpFile, "The name of the input process dump file.");
parser.DefineOptionalParameter("DataFile", ref DataFile, "The name of the file to place the heap snapshot.");
// TODO FIX NOW parser.DefineOptionalQualifier("DumpData", ref DumpData, "Dump the data as well as the connectivity information.");
parser.DefineParameterSet("GuiRun", ref DoCommand, App.CommandProcessor.GuiRun, "Opens the 'Run' dialog box.");
parser.DefineParameterSet("GuiCollect", ref DoCommand, App.CommandProcessor.GuiCollect, "Opens the 'Collect' dialog box.");
parser.DefineParameterSet("GuiHeapSnapshot", ref DoCommand, App.CommandProcessor.GuiHeapSnapshot,
"Opens the 'TakeHeapSnapshot' dialog box.");
parser.DefineParameterSet("UserCommand", ref DoCommand, App.CommandProcessor.UserCommand,
"Runs a user defined command. Type 'PerfView UserCommandHelp' to see the help for all the user commands. " +
"See PerfView Extensions in the users guide for more on creating user commands.");
parser.DefineParameter("CommandAndArgs", ref CommandAndArgs, "User command to run and any arguments.");
parser.DefineParameterSet("UserCommandHelp", ref DoCommand, App.CommandProcessor.UserCommandHelp,
"Displays help for user commands. Also see Help->User Command Help in the GUI.");
parser.DefineParameterSet("CreateExtensionProject", ref DoCommand, App.CommandProcessor.CreateExtensionProject,
"Creates a VS project for creates a perfView extension.");
parser.DefineOptionalParameter("ExtensionName", ref ExtensionName, "The name of the extension (no .DLL)");
#if CROSS_GENERATION_LIVENESS
parser.DefineParameterSet("CollectCrossGenerationLiveness", ref DoCommand, App.CommandProcessor.CollectCrossGenerationLiveness,
"Collect a heap snapshot that can be used to do cross-generation liveness analysis.");
parser.DefineQualifier("PID", ref CGL_PID, "The process ID of the process to snapshot.");
parser.DefineQualifier("Generation", ref CGL_Generation, "The generation of the GC to collect.");
parser.DefineQualifier("PromotedBytesThreshold", ref CGL_PromotedBytesThreshold, "The threshold of promoted bytes after which a snapshot of the heap should be collected.");
parser.DefineQualifier("OutputFile", ref CGL_PathToOutputFile, "The full path including filename where the resulting gcdump file should be stored.");
#endif
parser.DefineDefaultParameterSet(ref DoCommand, App.CommandProcessor.View, "View profile data.");
parser.DefineOptionalParameter("DataFile", ref DataFile, "ETL or ETLX file containing profile data.");
}
#endregion
};
}