Finding Performance Bottlenecks with dotnet-trace

Swift Kim


In this tutorial, you will learn how to profile a Tizen .NET application during startup to identify major performance issues using dotnet-trace.


First, install the following things on your device:

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


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.