1- # Using a device connected via USB
1+ # Tracing .NET Android Applications
22
3- ## Startup profiling
4- ### Set up reverse port forwarding:
3+ Attaching ` dotnet-trace ` to a .NET Android application, allows you to
4+ get profiling information in formats like ` .nettrace ` and
5+ ` .speedscope ` . These give you CPU sampling information about the time
6+ spent in each method in your application. This is quite useful for
7+ finding * where* time is spent in the startup or general performance of
8+ your .NET applications.
59
6- Note that you can skip this step if the Android application is running on an
7- Android emulator; it is only required for physical Android devices.
10+ To use ` dotnet-trace ` on Android, the following tools/components work
11+ together to make this happen:
812
9- ``` sh
10- $ adb reverse tcp:9000 tcp:9001
11- ```
12- This will forward port 9000 on device to port 9001.
13+ * [ ` dotnet-trace ` ] [ dotnet-trace ] itself is a .NET global tool.
1314
14- _ Alternatively:_
15- ``` sh
16- $ adb reverse tcp:0 tcp:9001
17- 43399
18- ```
19- This will allocate a random port on remote and forward it to port 9001 on the host. The forwarded port is printed by adb
15+ * [ ` dotnet-dsrouter ` ] [ dotnet-dsrouter ] is a .NET global tool that
16+ forwards a connection from a remote Android or iOS device or
17+ emulator to a local port on your development machine.
2018
21- ### Configure the device so that the profiled app suspends until tracing utility connects
19+ * [ ` dotnet-gcdump ` ] [ dotnet-gcdump ] is a .NET global tool that can be
20+ used to collect memory dumps of .NET applications.
2221
23- ``` sh
24- $ adb shell setprop debug.mono.profile ' 127.0.0.1:9000,suspend'
25- ```
22+ * The Mono Diagnostic component, ` libmono-component-diagnostics_tracing.so ` ,
23+ is included in the application and is used to collect the trace data.
24+
25+ See the [ ` dotnet-trace ` documentation] [ dotnet-trace ] for further details about its usage.
2626
27- ### Install ` dotnet-dsrouter `
27+ [ dotnet-trace ] : https://learn.microsoft.com/dotnet/core/diagnostics/dotnet-trace
28+ [ dotnet-dsrouter ] : https://learn.microsoft.com/dotnet/core/diagnostics/dotnet-dsrouter
29+ [ dotnet-gcdump ] : https://learn.microsoft.com/dotnet/core/diagnostics/dotnet-gcdump
2830
29- Generally, you can use a stable ` dotnet-dsrouter ` from NuGet:
31+ ## Install .NET Global Tools
32+
33+ Generally, you can install the required tooling such as:
3034
3135``` sh
36+ $ dotnet tool install -g dotnet-trace
37+ You can invoke the tool using the following command: dotnet-trace
38+ Tool ' dotnet-trace' was successfully installed.
3239$ dotnet tool install -g dotnet-dsrouter
3340You can invoke the tool using the following command: dotnet-dsrouter
3441Tool ' dotnet-dsrouter' was successfully installed.
42+ $ dotnet tool install -g dotnet-gcdump
43+ You can invoke the tool using the following command: dotnet-gcdump
44+ Tool ' dotnet-gcdump' was successfully installed.
3545```
3646
37- Or use a build from the nightly feed ` https://aka.ms/dotnet-tools/index.json ` :
47+ You can also install prerelease builds from the nightly feed
48+ ` https://aka.ms/dotnet-tools/index.json ` :
3849
3950``` sh
4051$ dotnet tool install -g dotnet-dsrouter --add-source=https://aka.ms/dotnet-tools/index.json --prerelease
52+ You can invoke the tool using the following command: dotnet-dsrouter
53+ Tool ' dotnet-dsrouter' was successfully installed.
4154```
4255
43- ### Start the tracing router/proxy on host
56+ ## Configuration & Setup
4457
45- For profiling an Android application running on an Android emulator:
46- ``` sh
47- $ dotnet-dsrouter android-emu --verbose debug
48- WARNING: dotnet-dsrouter is a development tool not intended for production environments.
58+ ### Running ` dotnet-dsrouter ` on the Host
59+
60+ For profiling an Android application running on an Android * emulator* :
4961
50- Start an application on android emulator with one of the following environment variables set:
62+ ``` sh
63+ $ dotnet-dsrouter android-emu
64+ How to connect current dotnet-dsrouter pid=1234 with android emulator and diagnostics tooling.
65+ Start an application on android emulator with ONE of the following environment variables set:
66+ [Default Tracing]
5167DOTNET_DiagnosticPorts=10.0.2.2:9000,nosuspend,connect
68+ [Startup Tracing]
5269DOTNET_DiagnosticPorts=10.0.2.2:9000,suspend,connect
70+ Run diagnotic tool connecting application on android emulator through dotnet-dsrouter pid=1234:
71+ dotnet-trace collect -p 1234
72+ See https://learn.microsoft.com/dotnet/core/diagnostics/dotnet-dsrouter for additional details and examples.
73+
74+ info: dotnet-dsrouter-1234[0]
75+ Starting dotnet-dsrouter using pid=1234
76+ info: dotnet-dsrouter-1234[0]
77+ Starting IPC server (dotnet-diagnostic-dsrouter-1234) < --> TCP server (127.0.0.1:9000) router.
78+ ```
5379
54- info: dotnet-dsrouter[0]
55- Starting dotnet-dsrouter using pid=21352
56- dbug: dotnet-dsrouter[0]
57- Using default IPC server path, dotnet-diagnostic-dsrouter-21352.
58- dbug: dotnet-dsrouter[0]
59- Attach to default dotnet-dsrouter IPC server using --process-id 21352 diagnostic tooling argument.
60- info: dotnet-dsrouter[0]
61- Starting IPC server (dotnet-diagnostic-dsrouter-21352) < --> TCP server (127.0.0.1:9000) router.
62- dbug: dotnet-dsrouter[0]
63- Trying to create new router instance.
64- dbug: dotnet-dsrouter[0]
65- Waiting for a new TCP connection at endpoint " 127.0.0.1:9000" .
66- dbug: dotnet-dsrouter[0]
67- Waiting for new ipc connection at endpoint " dotnet-diagnostic-dsrouter-21352" .
80+ For profiling an Android application running on an Android * device* :
81+
82+ ``` sh
83+ # `adb reverse` is required when using hardware devices
84+ $ adb reverse tcp:9000 tcp:9001
85+ $ dotnet-dsrouter android
86+ How to connect current dotnet-dsrouter pid=1234 with android device and diagnostics tooling.
87+ Start an application on android device with ONE of the following environment variables set:
88+ [Default Tracing]
89+ DOTNET_DiagnosticPorts=127.0.0.1:9000,nosuspend,connect
90+ [Startup Tracing]
91+ DOTNET_DiagnosticPorts=127.0.0.1:9000,suspend,connect
92+ Run diagnotic tool connecting application on android device through dotnet-dsrouter pid=1234:
93+ dotnet-trace collect -p 1234
94+ ...
6895```
6996
70- ### For Android devices
97+ ### Android System Properties
7198
72- For profiling an Android application running on an Android device:
99+ Note the log message that ` dotnet-dsrouter ` prints that mentions
100+ ` $DOTNET_DiagnosticPorts ` . ` $DOTNET_DiagnosticPorts ` is an environment
101+ variable that could be defined in an ` @(AndroidEnvironment) ` file, but
102+ it is simpler to use the ` debug.mono.profile ` Android system property.
103+ Android system properties can be used without rebuilding the app.
73104
105+ For emulators, ` $DOTNET_DiagnosticPorts ` should specify an IP address
106+ of 10.0.2.2:
107+
108+ ``` sh
109+ $ adb shell setprop debug.mono.profile ' 10.0.2.2:9000,suspend,connect'
74110```
75- $ dotnet-dsrouter server-server -tcps 127.0.0.1:9001 --verbose debug
111+
112+ For devices, ` $DOTNET_DiagnosticPorts ` should specify an IP address of
113+ 127.0.0.1, and the port number should be the [ port used used with adb
114+ reverse] ( #start-the-tracing-routerproxy-on-host ) , e.g:
115+
116+ ``` sh
117+ # `adb reverse` is required when using hardware devices
118+ $ adb reverse tcp:9000 tcp:9001
119+ $ adb shell setprop debug.mono.profile ' 127.0.0.1:9000,suspend,connect'
76120```
77121
78- Eventually, we will be able to simply do ` dotnet-dsrouter android ` when
79- [ dotnet/diagnostics #4337 ] [ 4337 ] is resolved. ` adb reverse tcp:9000 tcp:9001 ` is
80- also currently required as mentioned above.
122+ ` suspend ` is useful as it blocks application startup, so you can
123+ actually ` dotnet-trace ` startup times of the application.
124+
125+ If you are wanting to collect a ` gcdump ` or just get things working,
126+ try ` nosuspend ` instead. See the [ ` dotnet-dsrouter `
127+ documentation] [ nosuspend ] for further information.
81128
82- [ 4337 ] : https://github. com/dotnet/diagnostics/issues/4337
129+ [ nosuspend ] : https://learn.microsoft. com/dotnet/core/ diagnostics/dotnet-dsrouter#collect-a-trace-using-dotnet-trace-from-a-net-application-running-on-android
83130
84- ### Start the tracing client
131+ ### Running ` dotnet-trace ` on the Host
85132
86133First, run ` dotnet-trace ps ` to find a list of processes:
87134
88- ```
135+ ``` sh
89136> dotnet-trace ps
90137 38604 dotnet-dsrouter C:\U sers\m yuser\. dotnet\t ools\d otnet-dsrouter.exe " C:\Users\myuser\.dotnet\tools\dotnet-dsrouter.exe" android-emu --verbose debug
91138```
@@ -95,7 +142,7 @@ connect *through it* appropriately.
95142
96143Using the process ID from the previous step, run ` dotnet-trace collect ` :
97144
98- ```
145+ ``` sh
99146$ dotnet-trace collect -p 38604 --format speedscope
100147No profile or providers specified, defaulting to trace profile ' cpu-sampling'
101148
@@ -107,15 +154,23 @@ Waiting for connection on /tmp/maui-app
107154Start an application with the following environment variable: DOTNET_DiagnosticPorts=/tmp/maui-app
108155```
109156
110- The ` --format ` argument is optional and it defaults to ` nettrace ` . However, ` nettrace ` files can be viewed only with
111- Perfview on Windows, while the speedscope JSON files can be viewed "on" Unix by uploading them to https://speedscope.app
157+ The ` --format ` argument is optional and it defaults to ` nettrace ` .
158+ However, ` nettrace ` files can be viewed only with Perfview or Visual
159+ Studio on Windows, while the speedscope JSON files can be viewed "on"
160+ Unix by uploading them to [ https://speedscope.app/ ] [ speedscope ] .
112161
113- ### Compile and run the application
162+ [ speedscope ] : https://speedscope.app/
114163
115- ```
164+ ### Running the .NET Android Application
165+
166+ ` $(AndroidEnableProfiler) ` must be set to ` true ` as it includes the
167+ Mono diagnostic component in the application. This component is the
168+ ` libmono-component-diagnostics_tracing.so ` native library.
169+
170+ ``` sh
116171$ dotnet build -f net8.0-android -t:Run -c Release -p:AndroidEnableProfiler=true
117172```
118- _ NOTE : ` -f net8.0-android ` is only needed for projects with multiple ` $(TargetFrameworks) ` ._
173+ * NOTE : ` -f net8.0-android ` is only needed for projects with multiple ` $(TargetFrameworks) ` .*
119174
120175Once the application is installed and started, ` dotnet-trace ` should show something similar to:
121176
@@ -141,14 +196,8 @@ directory.
141196
142197## How to get GC memory dumps?
143198
144- If running on desktop, you can use the ` dotnet-gcdump ` global tool.
145- This can be installed via:
146-
147- ``` dotnetcli
148- $ dotnet tool install --global dotnet-gcdump
149- ```
150-
151- To use it, for example:
199+ If running on desktop, you can use the ` dotnet-gcdump ` global tool for
200+ local processes. For example:
152201
153202``` sh
154203# `hw-readline` is a standard Hello World, with a `Console.ReadLine()` at the end
@@ -167,6 +216,7 @@ $ dotnet-gcdump collect -p 33972
167216Writing gcdump to ' .../hw-readline/20230314_113922_33972.gcdump' ...
168217 Finished writing 5624131 bytes.
169218```
219+
170220See the [ ` dotnet-gcdump ` documentation] [ dotnet-gcdump ]
171221for further details about its usage.
172222
@@ -188,6 +238,9 @@ $ dotnet-gcdump collect -p 38604
188238
189239This will create a ` *.gcdump ` file in the current directory.
190240
241+ Note that using ` nosuspend ` in the ` debug.mono.profile ` property is
242+ useful, as it won't block application startup.
243+
191244## Memory Dumps for Android in .NET 7
192245
193246In .NET 7, we have to use th older, more complicated method for collecting
@@ -228,12 +281,11 @@ This saves a `foo.gcdump` that you can open in Visual Studio.
228281See the [ dotnet/runtime documentation] [ gc-dumps-on-mono ] for
229282additional details.
230283
231- [ dotnet-gcdump ] : https://learn.microsoft.com/dotnet/core/diagnostics/dotnet-gcdump
232284[ mono-events ] : https://github.com/dotnet/runtime/blob/c887c92d8af4ce65b19962b777f96ae8eb997a42/src/coreclr/vm/ClrEtwAll.man#L7433-L7468
233285[ dotnet-trace-help ] : https://github.com/dotnet/diagnostics/blob/6d755e8b5435b1380c118e9d81e075654b0330c9/documentation/dotnet-trace-instructions.md#dotnet-trace-help
234286[ gc-dumps-on-mono ] : https://github.com/dotnet/runtime/blob/728fd85bc7ad04f5a0ea2ad0d4d8afe371ff9b64/docs/design/mono/diagnostics-tracing.md#collect-gc-dumps-on-monovm
235287
236- ## How to ` dotnet trace ` our build ?
288+ ## How to ` dotnet trace ` a Build ?
237289
238290Setting this up is easy, the main issue is there end up being
239291potentially * a lot* of threads (30-40) depending on the build.
0 commit comments