Finding Performance Bottlenecks with dotnet-trace
Swift Kim
Engineer
In this tutorial, you will learn how to profile a Tizen .NET application during startup to identify major performance issues using dotnet-trace.
Prerequisites
First, install the following things on your device:
- .NET diagnostic tools (see Installing .NET diagnostic tools on Tizen devices)
- Target application (building an application in Debug mode may affect the result of profiling; make sure to build your application in Release mode)
Find loader process ID
A Tizen application is generally hosted by a pre-created process called loader. A loader process is automatically created by the system when it's in an idle state. To check if there is a free loader process running on your device, use dotnet trace ps
.
sh-3.2$ dotnet trace ps
3295 dotnet-loader /usr/bin/dotnet-loader
If a loader process is not found, install and run any .NET application on the device and try again.
Stack sampling
Using the process ID (PID) of the loader process you obtained in the previous step, you can collect the process's diagnostic trace using dotnet trace collect
.
-p PID
: Target process ID--format Speedscope
: Convert to the speedscope format-o PATH
: Output file path (.nettrace
)
sh-3.2$ dotnet trace collect -p 3295 --format Speedscope -o /home/owner/share/3295.nettrace
No profile or providers specified, defaulting to trace profile 'cpu-sampling'
Provider Name Keywords Level Enabled By
Microsoft-DotNETCore-SampleProfiler 0x0000000000000000 Informational(4) --profile
Microsoft-Windows-DotNETRuntime 0x00000014C14FCCBD Informational(4) --profile
Process : /usr/bin/dotnet-loader
Output File : /home/owner/share/3295.nettrace
[00:00:00:01] Recording trace 32.707 (KB)
If you see an output similar to the example above, launch an application from which you want to collect a trace (if the application is already running, terminate it before starting the trace). After the application launches completely, stop tracing by pressing Enter
.
[00:00:00:01] Recording trace 32.707 (KB)
Stopping the trace. This may take up to minutes depending on the application being traced.
Trace completed.
Writing: /home/owner/share/3295.speedscope.json
Conversion complete
A .speedscope.json
file is generated in the output directory.
Caution: You should have a write access to the specified output directory. Creating a file in an arbitrary directory may be denied by the SMACK security policy. The recommended output location is /home/owner/share
.
Analyzing the result
The .speedscope.json
file can be opened with a web-based tool called speedscope. First copy the file from the device to the host by running sdb pull /home/owner/share/3295.speedscope.json
, and import the file in the browser at https://www.speedscope.app.
In the viewer, you can see:
- Execution order of your application code
- Time-consuming methods and hot paths
- Costly work that can be lazily done after drawing the initial screen of the app
- Which thread is used to run an async
Task
at runtime and how long it lasts - etc.
Notice that the trace shows call paths for not only your own code but also external code. If you see any performance issues related with the external code, you should identify if it's your code misusing the external library, or the library itself has a defect or performance limitations.
To learn more about the speedscope viewer, check out the following pages.
Note: dotnet-trace collects thread stack information on a sampling basis. The default sampling interval is 1 ms. Some very short-running methods may not be recorded correctly.
Note: Native (unmanaged) callstacks (including P/Invoke frames) cannot be recorded by dotnet-trace. Using PerfCollect to trace native code execution is also not supported on Tizen.