dotnet-trace performance analysis utility
This article applies to: ✔️
dotnet-trace 3.0.47001 and later versions
There are two ways to download and install
dotnet global tool:
dotnet tool install --global dotnet-trace
Download the tool executable that matches your platform:
OS Platform Windows x86 | x64 | Arm | Arm-x64 Linux x64 | Arm | Arm64 | musl-x64 | musl-Arm64
dotnet-trace on an x86 app, you need a corresponding x86 version of the tool.
dotnet-trace [-h, --help] [--version] <command>
- Is a cross-platform .NET Core tool.
- Enables the collection of .NET Core traces of a running process without a native profiler.
- Is built on
EventPipeof the .NET Core runtime.
- Delivers the same experience on Windows, Linux, or macOS.
Shows command-line help.
Displays the version of the dotnet-trace utility.
How long to run the trace.
--duration 00:00:00:05will run it for 5 seconds.
Collects a diagnostic trace from a running process or launches a child process and traces it (.NET 5 or later). To have the tool run a child process and trace it from its startup, append
-- to the collect command.
dotnet-trace collect [--buffersize <size>] [--clreventlevel <clreventlevel>] [--clrevents <clrevents>] [--format <Chromium|NetTrace|Speedscope>] [-h|--help] [--duration dd:hh:mm:ss] [-n, --name <name>] [--diagnostic-port] [-o|--output <trace-file-path>] [-p|--process-id <pid>] [--profile <profile-name>] [--providers <list-of-comma-separated-providers>] [-- <command>] (for target applications running .NET 5 or later) [--show-child-io] [--resume-runtime] [--stopping-event-provider-name <stoppingEventProviderName>] [--stopping-event-event-name <stoppingEventEventName>] [--stopping-event-payload-filter <stoppingEventPayloadFilter>]
Sets the size of the in-memory buffer, in megabytes. Default 256 MB.
If the target process emits events faster than they can be written to disk, this buffer may overflow and some events will be dropped. You can mitigate this problem by increasing the buffer size or reducing the number of events being recorded.
Verbosity of CLR events to be emitted. The following table shows the available event levels.
String value Numeric value
A list of CLR runtime provider keywords to enable separated by
+signs. This is a simple mapping that lets you specify event keywords via string aliases rather than their hex values. For example,
dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:3:4requests the same set of events as
dotnet-trace collect --clrevents gc+gchandle --clreventlevel informational. The table below shows the list of available keywords:
Keyword String Alias Keyword Hex Value
You can read about the CLR provider more in detail on the .NET runtime provider reference documentation.
Sets the output format for the trace file conversion. The default is
-n, --name <name>
The name of the process to collect the trace from.
The name of the diagnostic port to create. See Use diagnostic port to collect a trace from app startup to learn how to use this option to collect a trace from app startup.
The time for the trace to run. Use the
dd:hh:mm:ssformat. For example
00:00:00:05will run it for 5 seconds.
The output path for the collected trace data. If not specified it defaults to
<appname>_<yyyyMMdd>_<HHmmss>.nettrace, e.g., `myapp_20210315_111514.nettrace``.
The process ID to collect the trace from.
A named pre-defined set of provider configurations that allows common tracing scenarios to be specified succinctly. The following profiles are available:
||Useful for tracking CPU usage and general .NET runtime information. This is the default option if no profile or providers are specified.|
||Tracks GC collections and samples object allocations.|
||Tracks GC collections only at very low overhead.|
A comma-separated list of
EventPipeproviders to be enabled. These providers supplement any providers implied by
--profile <profile-name>. If there's any inconsistency for a particular provider, this configuration takes precedence over the implicit configuration from the profile.
This list of providers is in the form:
Provideris in the form:
KeyValueArgsis in the form:
To learn more about some of the well-known providers in .NET, refer to Well-known Event Providers.
-- <command>(for target applications running .NET 5 or later)
After the collection configuration parameters, the user can append
--followed by a command to start a .NET application with at least a 5.0 runtime. This may be helpful when diagnosing issues that happen early in the process, such as startup performance issue or assembly loader and binder errors.
Using this option monitors the first .NET 5 process that communicates back to the tool, which means if your command launches multiple .NET applications, it will only collect the first app. Therefore, it is recommended you use this option on self-contained applications, or using the
dotnet exec <app.dll>option.
Shows the input and output streams of a launched child process in the current console.
Resume runtime once session has been initialized, defaults to true. Disable resume of runtime using --resume-runtime:false.
A string, parsed as-is, that will stop the trace upon hitting an event with the matching provider name. For a more specific stopping event, additionally provide
--stopping-event-provider-name Microsoft-Windows-DotNETRuntimeto stop the trace upon hitting the first event emitted by the
A string, parsed as-is, that will stop the trace upon hitting an event with the matching event name. Requires
--stopping-event-provider-nameto be set. For a more specific stopping event, additionally provide
--stopping-event-provider-name Microsoft-Windows-DotNETRuntime --stopping-event-event-name Method/JittingStartedto stop the trace upon hitting the first
Method/JittingStartedevent emitted by the
A string, parsed as [payload_field_name]:[payload_field_value] pairs separated by commas, that will stop the trace upon hitting an event containing all specified payload pairs. Requires
--stopping-event-event-nameto be set. e.g.
--stopping-event-provider-name Microsoft-Windows-DotNETRuntime --stopping-event-event-name Method/JittingStarted --stopping-event-payload-filter MethodNameSpace:Program,MethodName:OnButtonClickto stop the trace upon the first
Method/JittingStartedevent for the method
Programnamespace emitted by the
- Stopping the trace may take a long time (up to minutes) for large applications. The runtime needs to send over the type cache for all managed code that was captured in the trace.
- On Linux and macOS, this command expects the target application and
dotnet-traceto share the same
TMPDIRenvironment variable. Otherwise, the command will time out.
- To collect a trace using
dotnet-trace, it needs to be run as the same user as the user running the target process or as root. Otherwise, the tool will fail to establish a connection with the target process.
- If you see an error message similar to:
[ERROR] System.ComponentModel.Win32Exception (299): A 32 bit processes cannot access modules of a 64 bit process., you are trying to use a version of
dotnet-tracethat has mismatched bitness against the target process. Make sure to download the correct bitness of the tool in the install link.
- If you experience an unhandled exception while running
dotnet-trace collect, this results in an incomplete trace. If finding the root cause of the exception is your priority, navigate to Collect dumps on crash. As a result of the unhandled exception, the trace is truncated when the runtime shuts down to prevent other undesired behavior such as a hang or data corruption. Even though the trace is incomplete, you can still open it to see what happened leading up to the failure. However, it will be missing Rundown information (this happens at the end of a trace) so stacks might be unresolved (depending on what providers were turned on). Open the trace by executing PerfView with the
/ContinueOnErrorflag at the command line. The logs will also contain the location the exception was fired.
- When specifying a stopping event through the
--stopping-event-*options, as the EventStream is being parsed asynchronously, there will be some events that pass through between the time a trace event matching the specified stopping event options is parsed and the EventPipeSession is stopped.
nettrace traces to alternate formats for use with alternate trace analysis tools.
dotnet-trace convert [<input-filename>] [--format <Chromium|NetTrace|Speedscope>] [-h|--help] [-o|--output <output-filename>]
Input trace file to be converted. Defaults to trace.nettrace.
Sets the output format for the trace file conversion.
Output filename. Extension of target format will be added.
nettrace files to
speedscope files is irreversible.
chromium files don't have all the information necessary to reconstruct
nettrace files. However, the
convert command preserves the original
nettrace file, so don't delete this file if you plan to open it in the future.
Lists the dotnet processes that traces can be collected from.
dotnet-trace 6.0.320703 and later, also display the command-line arguments that each process was started with, if available.
dotnet-trace ps [-h|--help]
Suppose you start a long-running app using the command
dotnet run --configuration Release. In another window, you run the
dotnet-trace ps command. The output you'll see is as follows. The command-line arguments, if available, are shown in
dotnet-trace version 6.0.320703 and later.
> dotnet-trace ps 21932 dotnet C:\Program Files\dotnet\dotnet.exe run --configuration Release 36656 dotnet C:\Program Files\dotnet\dotnet.exe
Lists pre-built tracing profiles with a description of what providers and filters are in each profile.
dotnet-trace list-profiles [-h|--help]
Creates a report into stdout from a previously generated trace.
dotnet-trace report [-h|--help] <tracefile> [command]
The file path for the trace being analyzed.
dotnet-trace report topN
Finds the top N methods that have been on the callstack the longest.
dotnet-trace report <tracefile> topN [-n|--number <n>] [--inclusive] [-v|--verbose] [-h|--help]
Gives the top N methods on the callstack.
Output the top N methods based on inclusive time. If not specified, exclusive time is used by default.
Output the parameters of each method in full. If not specified, parameters will be truncated.
Collect a trace with dotnet-trace
To collect traces using
Get the process identifier (PID) of the .NET Core application to collect traces from.
- On Windows, you can use Task Manager or the
tasklistcommand, for example.
- On Linux, for example, the
- dotnet-trace ps
- On Windows, you can use Task Manager or the
Run the following command:
dotnet-trace collect --process-id <PID>
The preceding command generates output similar to the following:
Press <Enter> to exit... Connecting to process: <Full-Path-To-Process-Being-Profiled>/dotnet.exe Collecting to file: <Full-Path-To-Trace>/trace.nettrace Session Id: <SessionId> Recording trace 721.025 (KB)
Stop collection by pressing the
dotnet-tracewill finish logging events to the trace.nettrace file.
Launch a child application and collect a trace from its startup using dotnet-trace
This works for apps running .NET 5 or later only.
Sometimes it may be useful to collect a trace of a process from its startup. For apps running .NET 5 or later, it is possible to do this by using dotnet-trace.
This will launch
arg2 as its command-line arguments and collect a trace from its runtime startup:
dotnet-trace collect -- hello.exe arg1 arg2
The preceding command generates output similar to the following:
No profile or providers specified, defaulting to trace profile 'cpu-sampling' Provider Name Keywords Level Enabled By Microsoft-DotNETCore-SampleProfiler 0x0000F00000000000 Informational(4) --profile Microsoft-Windows-DotNETRuntime 0x00000014C14FCCBD Informational(4) --profile Process : E:\temp\gcperfsim\bin\Debug\net5.0\gcperfsim.exe Output File : E:\temp\gcperfsim\trace.nettrace [00:00:00:05] Recording trace 122.244 (KB) Press <Enter> or <Ctrl+C> to exit...
You can stop collecting the trace by pressing
<Ctrl + C> key. Doing this will also exit
hello.exe via dotnet-trace will redirect its input/output and you won't be able to interact with it on the console by default. Use the
--show-child-io switch to interact with its stdin/stdout.
Exiting the tool via CTRL+C or SIGTERM will safely end both the tool and the child process.
If the child process exits before the tool, the tool will exit as well and the trace should be safely viewable.
Use diagnostic port to collect a trace from app startup
This works for apps running .NET 5 or later only.
Diagnostic port is a runtime feature added in .NET 5 that allows you to start tracing from app startup. To do this using
dotnet-trace, you can either use
dotnet-trace collect -- <command> as described in the examples above, or use the
dotnet-trace <collect|monitor> -- <command> to launch the application as a child process is the simplest way to quickly trace the application from its startup.
However, when you want to gain a finer control over the lifetime of the app being traced (for example, monitor the app for the first 10 minutes only and continue executing) or if you need to interact with the app using the CLI, using
--diagnostic-port option allows you to control both the target app being monitored and
The command below makes
dotnet-tracecreate a diagnostics socket named
myport.sockand wait for a connection.
dotnet-trace collect --diagnostic-port myport.sock
Waiting for connection on myport.sock Start an application with the following environment variable: DOTNET_DiagnosticPorts=/home/user/myport.sock
In a separate console, launch the target application with the environment variable
DOTNET_DiagnosticPortsset to the value in the
export DOTNET_DiagnosticPorts=/home/user/myport.sock ./my-dotnet-app arg1 arg2
This should then enable
dotnet-traceto start tracing
Waiting for connection on myport.sock Start an application with the following environment variable: DOTNET_DiagnosticPorts=myport.sock Starting a counter session. Press Q to quit.
Launching your app with
dotnet runcan be problematic because the dotnet CLI may spawn many child processes that are not your app and they can connect to
dotnet-tracebefore your app, leaving your app to be suspended at run time. It is recommended you directly use a self-contained version of the app or use
dotnet execto launch the application.
View the trace captured from dotnet-trace
On Linux, you can view the trace by changing the output format of
speedscope. Change the output file format by using the
-f|--format option. You can choose between
nettrace (the default option) and
speedscope. The option
-f speedscope will make
dotnet-trace produce a
Speedscope files can be opened at https://www.speedscope.app.
For traces collected on non-Windows platforms, you can also move the trace file to a Windows machine and view it in Visual Studio or PerfView.
The .NET Core runtime generates traces in the
nettrace format. The traces are converted to speedscope (if specified) after the trace is completed. Since some conversions may result in loss of data, the original
nettrace file is preserved next to the converted file.
Use dotnet-trace to collect counter values over time
EventCounterfor basic health monitoring in performance-sensitive environments. For example, in production.
- Collect traces so they don't need to be viewed in real time.
For example, to collect runtime performance counter values, use the following command:
dotnet-trace collect --process-id <PID> --providers System.Runtime:0:1:EventCounterIntervalSec=1
The preceding command tells the runtime counters to report once every second for lightweight health monitoring. Replacing
EventCounterIntervalSec=1 with a higher value (for example, 60) allows collection of a smaller trace with less granularity in the counter data.
The following command reduces overhead and trace size more than the preceding one:
dotnet-trace collect --process-id <PID> --providers System.Runtime:0:1:EventCounterIntervalSec=1,Microsoft-Windows-DotNETRuntime:0:1,Microsoft-DotNETCore-SampleProfiler:0:1
The preceding command disables runtime events and the managed stack profiler.
Use .rsp file to avoid typing long commands
You can launch
dotnet-trace with an
.rsp file that contains the arguments to pass. This can be useful when enabling providers that expect lengthy arguments or when using a shell environment that strips characters.
For example, the following provider can be cumbersome to type out each time you want to trace:
In addition, the previous example contains
" as part of the argument. Because quotes are not handled equally by each shell, you may experience various issues when using different shells. For example, the command to enter in
zsh is different to the command in
Instead of typing this each time, you can save the following text into a file called
Once you've saved
myprofile.rsp, you can launch
dotnet-trace with this configuration using the following command: