1
- # Using a device connected via USB
1
+ # Tracing .NET Android Applications
2
2
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.
5
9
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:
8
12
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.
13
14
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.
20
18
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.
22
21
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.
26
26
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
28
30
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:
30
34
31
35
``` 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.
32
39
$ dotnet tool install -g dotnet-dsrouter
33
40
You can invoke the tool using the following command: dotnet-dsrouter
34
41
Tool ' 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.
35
45
```
36
46
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 ` :
38
49
39
50
``` sh
40
51
$ 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.
41
54
```
42
55
43
- ### Start the tracing router/proxy on host
56
+ ## Configuration & Setup
44
57
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* :
49
61
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]
51
67
DOTNET_DiagnosticPorts=10.0.2.2:9000,nosuspend,connect
68
+ [Startup Tracing]
52
69
DOTNET_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
+ ```
53
79
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
+ ...
68
95
```
69
96
70
- ### For Android devices
97
+ ### Android System Properties
71
98
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.
73
104
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'
74
110
```
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'
76
120
```
77
121
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.
81
128
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
83
130
84
- ### Start the tracing client
131
+ ### Running ` dotnet-trace ` on the Host
85
132
86
133
First, run ` dotnet-trace ps ` to find a list of processes:
87
134
88
- ```
135
+ ``` sh
89
136
> dotnet-trace ps
90
137
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
91
138
```
@@ -95,7 +142,7 @@ connect *through it* appropriately.
95
142
96
143
Using the process ID from the previous step, run ` dotnet-trace collect ` :
97
144
98
- ```
145
+ ``` sh
99
146
$ dotnet-trace collect -p 38604 --format speedscope
100
147
No profile or providers specified, defaulting to trace profile ' cpu-sampling'
101
148
@@ -107,15 +154,23 @@ Waiting for connection on /tmp/maui-app
107
154
Start an application with the following environment variable: DOTNET_DiagnosticPorts=/tmp/maui-app
108
155
```
109
156
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 ] .
112
161
113
- ### Compile and run the application
162
+ [ speedscope ] : https://speedscope.app/
114
163
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
116
171
$ dotnet build -f net8.0-android -t:Run -c Release -p:AndroidEnableProfiler=true
117
172
```
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) ` .*
119
174
120
175
Once the application is installed and started, ` dotnet-trace ` should show something similar to:
121
176
@@ -141,14 +196,8 @@ directory.
141
196
142
197
## How to get GC memory dumps?
143
198
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:
152
201
153
202
``` sh
154
203
# `hw-readline` is a standard Hello World, with a `Console.ReadLine()` at the end
@@ -167,6 +216,7 @@ $ dotnet-gcdump collect -p 33972
167
216
Writing gcdump to ' .../hw-readline/20230314_113922_33972.gcdump' ...
168
217
Finished writing 5624131 bytes.
169
218
```
219
+
170
220
See the [ ` dotnet-gcdump ` documentation] [ dotnet-gcdump ]
171
221
for further details about its usage.
172
222
@@ -188,6 +238,9 @@ $ dotnet-gcdump collect -p 38604
188
238
189
239
This will create a ` *.gcdump ` file in the current directory.
190
240
241
+ Note that using ` nosuspend ` in the ` debug.mono.profile ` property is
242
+ useful, as it won't block application startup.
243
+
191
244
## Memory Dumps for Android in .NET 7
192
245
193
246
In .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.
228
281
See the [ dotnet/runtime documentation] [ gc-dumps-on-mono ] for
229
282
additional details.
230
283
231
- [ dotnet-gcdump ] : https://learn.microsoft.com/dotnet/core/diagnostics/dotnet-gcdump
232
284
[ mono-events ] : https://github.com/dotnet/runtime/blob/c887c92d8af4ce65b19962b777f96ae8eb997a42/src/coreclr/vm/ClrEtwAll.man#L7433-L7468
233
285
[ dotnet-trace-help ] : https://github.com/dotnet/diagnostics/blob/6d755e8b5435b1380c118e9d81e075654b0330c9/documentation/dotnet-trace-instructions.md#dotnet-trace-help
234
286
[ gc-dumps-on-mono ] : https://github.com/dotnet/runtime/blob/728fd85bc7ad04f5a0ea2ad0d4d8afe371ff9b64/docs/design/mono/diagnostics-tracing.md#collect-gc-dumps-on-monovm
235
287
236
- ## How to ` dotnet trace ` our build ?
288
+ ## How to ` dotnet trace ` a Build ?
237
289
238
290
Setting this up is easy, the main issue is there end up being
239
291
potentially * a lot* of threads (30-40) depending on the build.
0 commit comments