Use dotTrace Command-Line Profiler
Sometimes it is necessary to automate the process of gathering performance snapshots, for example, if you want to make profiling a part of your continuous integration builds (for example, this can be a build step that performs profiling of your integration tests). For this purpose, dotTrace offers a set of command-line tools for Windows, macOS, and Linux:
OS | Tools | Distribution |
---|---|---|
Windows |
| |
macOS |
| |
Linux |
|
note
* If your domain policy is to treat the files downloaded from the Internet as unsafe, unblock the zip archive using the Unblock button in file properties.
warning
The Timeline profiling type requires running JetBrains ETW Host Service with administrative privileges.
Depending on your profiling scenario, run dotTrace.exe with the options you need. For example:
To run and profile a standalone application App.exe using the Timeline profiling type:
dotTrace.exe start --save-to=c:\Snapshots\snapshot.dtt --profiling-type=Timeline c:\MyApp\App.exe
To run and profile a standalone application App.exe (using the default Sampling profiling type) and control the session using the profiling API:
dotTrace.exe start --save-to=c:\Snapshots\snapshot.dtp c:\MyApp\App.exe --use-api
To attach to a running application with
PID=1234
and profile it using the sampling profiling type:dotTrace.exe attach 1234 --save-to=c:\Snapshots\snapshot.dtp
To see the full list of available options, run the tool without any arguments:
dotTrace.exe
After the profiled application finishes working, the command-line profiler will automatically save a performance snapshot.
If you want to take snapshots manually at any time, you can do this by sending messages to stdin of the profiler or to a file on disk.
Analyze the snapshot using the standalone dotTrace, dotTrace in Rider, or using the reporter tool.
Depending on your profiling scenario, run dotTrace.sh with the options you need. For example:
To run and profile a Mono application myMonoApp:
./dotTrace.sh start --framework=Mono /usr/bin/mono /home/Projects/MyMonoApp/myMonoApp --profiling-type=Timeline --timeout=10s --save-to=./snapshots/snapshot.dtt
Note that we must specify
/usr/bin/mono
as a profiling target and use theTimeline
profiling type (other types are not supported for Mono on macOS and Linux).To run and profile a .NET Core 3.1 (or later) application MyNetCoreApp.dll:
./dotTrace.sh start --framework=NetCore /usr/bin/dotnet /home/Projects/MyNetCoreApp/MyNetCoreApp.dll --timeout=10s --save-to=./snapshots/snapshot.dtp
To run and profile a .NET Core 3.0 (or earlier) application MyNetCoreApp.dll:
./dotTrace.sh start --framework=NetCore /usr/bin/dotnet /home/Projects/MyNetCoreApp/MyNetCoreApp.dll --support-earlier-net-core --timeout=10s --save-to=./snapshots/snapshot.dtp
To attach to a running application with
PID=1234
and profile it using the sampling profiling type:./dotTrace.sh attach 1234 --save-to=./snapshots/snapshot.dtp
To see the full list of available options, run the tool without any arguments:
./dotTrace.sh
After the profiled application finishes working, the command-line profiler will automatically save a performance snapshot.
note
dotTrace on macOS and Linux has the following limitations:
Attaching to running applications is available on Linux for .NET Core 3.0 or later and on macOS for .NET 5 or later.
Only Timeline profiling type is available for Mono and Unity apps.
Line-by-line profiling type is not available for .NET Core apps.
Because of .NET Core limitations, .NET Core 3.0 (or earlier) applications may hang or crash during profiling. .NET Core 3.1 (or later) applications are profiled without any issues.
Cross-user profiling is not supported: A user cannot profile a process that was run on behalf of another user.
Analyze the snapshot using the standalone dotTrace, or dotTrace in Rider.
note
Snapshots are saved in the raw format. For the Sampling profiling type, specify
.dtp
as a snapshot file extension. For Timeline, specify.dtt
.
Sometimes it's necessary to have direct control over the profiling process, for example, get a snapshot at some exact moment by a direct command. This can be done by:
sending messages to stdin of
dotTrace.exe
|dotTrace.sh
,writing messages to a file on disk.
warning
Messages sent to stdin (written to a file) must always start with a new line and end with a carriage return. Both stdin and stdout messages have a format of a JSON array.
You can start profiling using the
attach
orstart
command.If you want to control a session using stdin:
dotTrace.exe start --service-input=stdin c:\MyApp\MyApp.exe
If you want to control a session using a file:
dotTrace.exe start --service-input=file.txt c:\MyApp\MyApp.exe
Note that you must create the file before running the session.
Get a snapshot by sending the following command to stdin or writing it to file.txt:
##dotTrace["get-snapshot", {pid:1234}]
If
pid
is specified, dotTrace will take a snapshot of the process with the specified PID. Otherwise, dotTrace will take snapshots of all profiled processes.To stop profiling and kill the profiled application, send the following command to stdin or file.txt:
##dotTrace["disconnect"]
dotTrace informs you about how the profiling process is going by sending special service messages to stdout. This might be especially helpful in case you control profiling by some external script. An example of the output:
D:\dotTrace> .\dotTrace.exe start --service-input=stdin C:\MyApp\MyApp.exe
dotTrace Console Profiler 2020.2 Copyright (C) 2020 JetBrains s.r.o.
Profiling in progress...
##dotTrace["ready"]
You can control profiling by sending command messages to stdin. For details, type ##dotTrace["help"]
Executable='C:\MyApp\MyApp.exe' (non-child) is being passed for filtering
Passed filter executable='C:\MyApp\MyApp.exe'
##dotTrace["connected",{"pid":19016,"path":"C:\\MyApp\\MyApp.exe"}]
##dotTrace["started",{"pid":19016,"path":"C:\\MyApp\\MyApp.exe"}]
##dotTrace["get-snapshot"]
##dotTrace["stopped",{"pid":19016,"path":"C:\\MyApp\\MyApp.exe"}]
##dotTrace["snapshot-saved",{"pid":19016,"filename":"D:\\dotTrace\\Zupifix.dtp"}]
You can start profiling using the
attach
orstart
command.If you want to control a session using stdin:
./dotTrace.sh start --framework=NetCore --service-input=stdin ~/MyApp/myApp
If you want to control a session using a file:
./dotTrace.sh start --framework=NetCore --service-input=file.txt ~/MyApp/myApp
Note that you must create the file before running the session.
Get a snapshot by sending the following command to stdin or writing it to file.txt:
##dotTrace["get-snapshot", {pid:1234}]
If
pid
is specified, dotTrace will take a snapshot of the process with the specified PID. Otherwise, dotTrace will take snapshots of all profiled processes.To stop profiling and kill the profiled application, send the following command to stdin or file.txt:
##dotTrace["disconnect"]
dotTrace informs you about how the profiling process is going by sending special service messages to stdout. This might be especially helpful in case you control profiling by some external script. An example of the output:
./dotTrace.sh start --framework=NetCore --service-input=stdin ~/MyApp/myApp
dotTrace Console Profiler 2020.2 Copyright (C) 2020 JetBrains s.r.o.
Profiling in progress...
##dotTrace["ready"]
You can control profiling by sending command messages to stdin.
For details, type ##dotTrace["help"]
Executable='~/MyApp/myApp' (non-child) is being passed for filtering
Passed filter executable='~/MyApp/myApp'
##dotTrace["connected",{"pid":19016,"path":"~/MyApp/myApp"}]
##dotTrace["started",{"pid":19016,"path":"~/MyApp/myApp"}]
##dotTrace["get-snapshot"]
##dotTrace["stopped",{"pid":19016,"path":"~/MyApp/myApp"}]
##dotTrace["snapshot-saved",{"pid":19016,"filename":"~/dotTrace/Zupifix.dtp"}]
By default, if the tool finishes its work successfully, its exit code is 0
. This may be inconvenient in some cases. For example, if you run the tool on a CI server, you may need to get the exit code of the profiled application (for example, a unit test runner). To make the profiler return the exit code of the profiling target, use the --propagate-exit-code
argument.
For example (on Windows):
dotTrace.exe start --save-to=c:\Snapshots\snapshot.dtp
--profiling-type=Sampling c:\MyApp\App.exe --propagate-exit-code
In the section above, we have provided the profiling configuration (profiling target, profiling method, and so on) as the dotTrace.exe arguments. If you do not want to configure a session this way, you can provide the configuration in an XML file.
To simplify file creation, you can use the Configuration2Xml32.exe (and the 64-bit version Configuration2Xml64.exe) tool. This tool allows you to create the XML configuration file using the familiar user interface of the dotTrace Home window.
Run the Configuration2Xml32.exe or Configuration2Xml64.exe tool which is located in the dotTrace installation directory (by default, C:
\Users ).\[username] \AppData \Local \JetBrains \Installations \dotTrace[N] To create a new profiling configuration, select the Create New Config menu.
To modify an existing profiling configuration, select Open Config.
Specify profiling options as you normally do in the dotTrace Home window.
Click Save and specify the filename and path for the configuration file.
Click Save.
Run the following command in the command line:
dotTrace.exe xmlfile <path_to_config> --save-to=<path_to_snapshot>
where:
<path_to_config>
- path to the XML configuration file.<path_to_snapshot>
- path to the resulting snapshot file. Note that you can specify either the full path (including the snapshot filename) or only the path to the directory without the filename. In the latter case, the snapshot file will get a random name.
For example:
dotTrace.exe xmlfile config.xml --save-to=c:\Snapshots\snapshot.dtp
If you have .NET Core 3.1.0 or later on your machine, you can install and use the dotTrace command-line tool as a .NET Core global and local tool.
To install the dotTrace command-line tool as a global .NET Core tool in the default location, run the following command line:
dotnet tool install --global JetBrains.dotTrace.GlobalTools
To install the dotTrace command-line tool as a local tool, you can execute the following locally:
dotnet new tool-manifest dotnet tool install JetBrains.dotTrace.GlobalTools
For further instructions, refer to the official Microsoft documentation.
Use the
dottrace
command to run profiling. The command accepts the same arguments asdotTrace.exe
(on Windows) ordotTrace.sh
(on Linux and macOS). For example, to start timeline profiling of MyApp.exe, open the solution directory and run:dottrace start --profiling-type=Timeline .\MyApp\bin\Release\MyApp.exe
warning
The Reporter.exe tool does NOT work with snapshots taken using the Timeline profiling type.
The Reporter.exe tool can work in two modes:
Getting performance data for particular methods.
The resulting XML report gets data on execution time and number of calls* for particular methods.
The resulting XML report gets data on differences in execution time and number of calls* for particular methods. This mode can be especially useful for comparing performance data you get in a latest build against some reference snapshot.
note
* Number of calls is shown only for the Tracing and Line-by-Line profiling types.
Regardless of the mode you choose, you should specify method names that should be added to the report.
The list of methods that must be added into a report is defined by an XML pattern file.
In an editor of your choice, create a blank XML file.
Write the list of methods that must be added to the report as shown in the example below.
<Patterns> <Pattern PrintCallstacks = "MethodNameOnly">Method1</Pattern> <Pattern>Method2</Pattern> </Patterns>
where:
Method1
andMethod2
- a regular expression that matches names (not substrings of names) of the methods you want to get the performance data for. Note that if a method name contains special characters, you should escape them with the backslash\
symbol. For example,MyMethod\+MySubMethod
.PrintCallstacks
- optional attribute that allows including call stack data in reports (an example of such a report is shown below). There are two available values forPrintCallstacks
:Full
- fully qualified method names will be shown in the call stack.MethodNameOnly
- only method names (without namespace and class names) will be shown in the call stack.
Save the file.
In the command line, run the following command:
Reporter.exe report <path_to_snapshot> --pattern=<path_to_pattern> --save-to=<path_to_report>
where:
<path_to_snapshot>
- path to the source snapshot file.<path_to_pattern>
- path to the XML pattern file which contains names of the methods added to the report.<path_to_report>
- path to the resulting report file.
For example:
Reporter.exe report c:\Snapshots\snapshot.dtp --pattern=pattern.xml --save-to=c:\Reports\report.xml
<Report>
<Info>
<Snapshot IndexFile="C:\snapshot1.dtp" Executable="C:\Temp\ConsoleAppTest.exe"
CommandLine="C:\Temp\ConsoleAppTest.exe" />
</Info>
<Function FQN="Tests.Method1" TotalTime="500" OwnTime="100" Calls="1" />
<Function FQN="Tests.Method2" TotalTime="400" OwnTime="200" Calls="10" />
</Report>
where:
FQN
- full method name.TotalTime
- execution time of the method's call subtree.OwnTime
- method's own execution time.Calls
- number of calls.
If a PrintCallstacks
attribute was specified for a particular Pattern
in an XML pattern file, the report will contain additional call stack data. For example, <Pattern PrintCallstacks = "MethodNameOnly">
was specified for some GetFileNames
function. In this case, the corresponding Function
node in the resulting report will contain an additional Instance
subnode with a call stack:
<Function Id="0x0020000C" FQN="MyApplication.MainWindow.GetFileNames" TotalTime="12520" OwnTime="0" Calls="1740" Instances="1">
<Instance CallStack="Main/Run/Run/RunInternal/RunDispatcher/PushFrame/PushFrameImpl/OnClick/RaiseEvent/RaiseEventImpl/InvokeHandlersImpl/InvokeHandler/btnSelectFiles_Click/GetFileNames" TotalTime="12520" OwnTime="0" Calls="1740" />
</Function>
note
In case you want to distinguish overloaded methods in a report, run
Reporter.exe
with the--save-signature
argument.
In the command line, run the following command:
Reporter.exe compare <path_to_snapshot1> <path_to_snapshot2> --pattern=<path_to_pattern> --save-to=<path_to_report>
where:
<path_to_snapshot1>
- path to the reference snapshot file.<path_to_snapshot2>
- path to the second snapshot file.<path_to_pattern>
- path to the XML pattern file which contains names of the methods added to the report.<path_to_report>
- path to the resulting report file.
For example:
Reporter.exe compare c:\Snapshots\base_snapshot.dtp c:\Snapshots\snapshot.dtp
--pattern=pattern.xml --save-to=c:\Reports\report.xml
The resulting report file is similar to the one you get in the "reporting" mode with the only difference: all fields will contain not the absolute time or number of calls values but their delta between the snapshots. Depending on the delta sign, the values will start with either +
or -
prefix.