Skip to content

Commit

Permalink
Merge branch 'main' into dev/grendel/xxhash3
Browse files Browse the repository at this point in the history
* main:
  [templates] Remove redundant "template" from display name. (#8773)
  Bump to xamarin/Java.Interop/main@a7e09b7 (#8793)
  [build] Include MIT license in most NuGet packages (#8787)
  Bump to dotnet/installer@893b762b6e 9.0.100-preview.3.24153.2 (#8782)
  [docs] update notes about `dotnet-trace` and `dotnet-gcdump` (#8713)
  • Loading branch information
grendello committed Mar 8, 2024
2 parents 1a8e48c + 9d8ca60 commit f85a6ae
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 94 deletions.
186 changes: 119 additions & 67 deletions Documentation/guides/tracing.md
Original file line number Diff line number Diff line change
@@ -1,91 +1,138 @@
# Using a device connected via USB
# Tracing .NET Android Applications

## Startup profiling
### Set up reverse port forwarding:
Attaching `dotnet-trace` to a .NET Android application, allows you to
get profiling information in formats like `.nettrace` and
`.speedscope`. These give you CPU sampling information about the time
spent in each method in your application. This is quite useful for
finding *where* time is spent in the startup or general performance of
your .NET applications.

Note that you can skip this step if the Android application is running on an
Android emulator; it is only required for physical Android devices.
To use `dotnet-trace` on Android, the following tools/components work
together to make this happen:

```sh
$ adb reverse tcp:9000 tcp:9001
```
This will forward port 9000 on device to port 9001.
* [`dotnet-trace`][dotnet-trace] itself is a .NET global tool.

_Alternatively:_
```sh
$ adb reverse tcp:0 tcp:9001
43399
```
This will allocate a random port on remote and forward it to port 9001 on the host. The forwarded port is printed by adb
* [`dotnet-dsrouter`][dotnet-dsrouter] is a .NET global tool that
forwards a connection from a remote Android or iOS device or
emulator to a local port on your development machine.

### Configure the device so that the profiled app suspends until tracing utility connects
* [`dotnet-gcdump`][dotnet-gcdump] is a .NET global tool that can be
used to collect memory dumps of .NET applications.

```sh
$ adb shell setprop debug.mono.profile '127.0.0.1:9000,suspend'
```
* The Mono Diagnostic component, `libmono-component-diagnostics_tracing.so`,
is included in the application and is used to collect the trace data.

See the [`dotnet-trace` documentation][dotnet-trace] for further details about its usage.

### Install `dotnet-dsrouter`
[dotnet-trace]: https://learn.microsoft.com/dotnet/core/diagnostics/dotnet-trace
[dotnet-dsrouter]: https://learn.microsoft.com/dotnet/core/diagnostics/dotnet-dsrouter
[dotnet-gcdump]: https://learn.microsoft.com/dotnet/core/diagnostics/dotnet-gcdump

Generally, you can use a stable `dotnet-dsrouter` from NuGet:
## Install .NET Global Tools

Generally, you can install the required tooling such as:

```sh
$ dotnet tool install -g dotnet-trace
You can invoke the tool using the following command: dotnet-trace
Tool 'dotnet-trace' was successfully installed.
$ dotnet tool install -g dotnet-dsrouter
You can invoke the tool using the following command: dotnet-dsrouter
Tool 'dotnet-dsrouter' was successfully installed.
$ dotnet tool install -g dotnet-gcdump
You can invoke the tool using the following command: dotnet-gcdump
Tool 'dotnet-gcdump' was successfully installed.
```

Or use a build from the nightly feed `https://aka.ms/dotnet-tools/index.json`:
You can also install prerelease builds from the nightly feed
`https://aka.ms/dotnet-tools/index.json`:

```sh
$ dotnet tool install -g dotnet-dsrouter --add-source=https://aka.ms/dotnet-tools/index.json --prerelease
You can invoke the tool using the following command: dotnet-dsrouter
Tool 'dotnet-dsrouter' was successfully installed.
```

### Start the tracing router/proxy on host
## Configuration & Setup

For profiling an Android application running on an Android emulator:
```sh
$ dotnet-dsrouter android-emu --verbose debug
WARNING: dotnet-dsrouter is a development tool not intended for production environments.
### Running `dotnet-dsrouter` on the Host

For profiling an Android application running on an Android *emulator*:

Start an application on android emulator with one of the following environment variables set:
```sh
$ dotnet-dsrouter android-emu
How to connect current dotnet-dsrouter pid=1234 with android emulator and diagnostics tooling.
Start an application on android emulator with ONE of the following environment variables set:
[Default Tracing]
DOTNET_DiagnosticPorts=10.0.2.2:9000,nosuspend,connect
[Startup Tracing]
DOTNET_DiagnosticPorts=10.0.2.2:9000,suspend,connect
Run diagnotic tool connecting application on android emulator through dotnet-dsrouter pid=1234:
dotnet-trace collect -p 1234
See https://learn.microsoft.com/dotnet/core/diagnostics/dotnet-dsrouter for additional details and examples.

info: dotnet-dsrouter-1234[0]
Starting dotnet-dsrouter using pid=1234
info: dotnet-dsrouter-1234[0]
Starting IPC server (dotnet-diagnostic-dsrouter-1234) <--> TCP server (127.0.0.1:9000) router.
```

info: dotnet-dsrouter[0]
Starting dotnet-dsrouter using pid=21352
dbug: dotnet-dsrouter[0]
Using default IPC server path, dotnet-diagnostic-dsrouter-21352.
dbug: dotnet-dsrouter[0]
Attach to default dotnet-dsrouter IPC server using --process-id 21352 diagnostic tooling argument.
info: dotnet-dsrouter[0]
Starting IPC server (dotnet-diagnostic-dsrouter-21352) <--> TCP server (127.0.0.1:9000) router.
dbug: dotnet-dsrouter[0]
Trying to create new router instance.
dbug: dotnet-dsrouter[0]
Waiting for a new TCP connection at endpoint "127.0.0.1:9000".
dbug: dotnet-dsrouter[0]
Waiting for new ipc connection at endpoint "dotnet-diagnostic-dsrouter-21352".
For profiling an Android application running on an Android *device*:

```sh
# `adb reverse` is required when using hardware devices
$ adb reverse tcp:9000 tcp:9001
$ dotnet-dsrouter android
How to connect current dotnet-dsrouter pid=1234 with android device and diagnostics tooling.
Start an application on android device with ONE of the following environment variables set:
[Default Tracing]
DOTNET_DiagnosticPorts=127.0.0.1:9000,nosuspend,connect
[Startup Tracing]
DOTNET_DiagnosticPorts=127.0.0.1:9000,suspend,connect
Run diagnotic tool connecting application on android device through dotnet-dsrouter pid=1234:
dotnet-trace collect -p 1234
...
```

### For Android devices
### Android System Properties

For profiling an Android application running on an Android device:
Note the log message that `dotnet-dsrouter` prints that mentions
`$DOTNET_DiagnosticPorts`. `$DOTNET_DiagnosticPorts` is an environment
variable that could be defined in an `@(AndroidEnvironment)` file, but
it is simpler to use the `debug.mono.profile` Android system property.
Android system properties can be used without rebuilding the app.

For emulators, `$DOTNET_DiagnosticPorts` should specify an IP address
of 10.0.2.2:

```sh
$ adb shell setprop debug.mono.profile '10.0.2.2:9000,suspend,connect'
```
$ dotnet-dsrouter server-server -tcps 127.0.0.1:9001 --verbose debug

For devices, `$DOTNET_DiagnosticPorts` should specify an IP address of
127.0.0.1, and the port number should be the [port used used with adb
reverse](#start-the-tracing-routerproxy-on-host), e.g:

```sh
# `adb reverse` is required when using hardware devices
$ adb reverse tcp:9000 tcp:9001
$ adb shell setprop debug.mono.profile '127.0.0.1:9000,suspend,connect'
```

Eventually, we will be able to simply do `dotnet-dsrouter android` when
[dotnet/diagnostics#4337][4337] is resolved. `adb reverse tcp:9000 tcp:9001` is
also currently required as mentioned above.
`suspend` is useful as it blocks application startup, so you can
actually `dotnet-trace` startup times of the application.

If you are wanting to collect a `gcdump` or just get things working,
try `nosuspend` instead. See the [`dotnet-dsrouter`
documentation][nosuspend] for further information.

[4337]: https://github.com/dotnet/diagnostics/issues/4337
[nosuspend]: https://learn.microsoft.com/dotnet/core/diagnostics/dotnet-dsrouter#collect-a-trace-using-dotnet-trace-from-a-net-application-running-on-android

### Start the tracing client
### Running `dotnet-trace` on the Host

First, run `dotnet-trace ps` to find a list of processes:

```
```sh
> dotnet-trace ps
38604 dotnet-dsrouter C:\Users\myuser\.dotnet\tools\dotnet-dsrouter.exe "C:\Users\myuser\.dotnet\tools\dotnet-dsrouter.exe" android-emu --verbose debug
```
Expand All @@ -95,7 +142,7 @@ connect *through it* appropriately.

Using the process ID from the previous step, run `dotnet-trace collect`:

```
```sh
$ dotnet-trace collect -p 38604 --format speedscope
No profile or providers specified, defaulting to trace profile 'cpu-sampling'

Expand All @@ -107,15 +154,23 @@ Waiting for connection on /tmp/maui-app
Start an application with the following environment variable: DOTNET_DiagnosticPorts=/tmp/maui-app
```

The `--format` argument is optional and it defaults to `nettrace`. However, `nettrace` files can be viewed only with
Perfview on Windows, while the speedscope JSON files can be viewed "on" Unix by uploading them to https://speedscope.app
The `--format` argument is optional and it defaults to `nettrace`.
However, `nettrace` files can be viewed only with Perfview or Visual
Studio on Windows, while the speedscope JSON files can be viewed "on"
Unix by uploading them to [https://speedscope.app/][speedscope].

### Compile and run the application
[speedscope]: https://speedscope.app/

```
### Running the .NET Android Application

`$(AndroidEnableProfiler)` must be set to `true` as it includes the
Mono diagnostic component in the application. This component is the
`libmono-component-diagnostics_tracing.so` native library.

```sh
$ dotnet build -f net8.0-android -t:Run -c Release -p:AndroidEnableProfiler=true
```
_NOTE: `-f net8.0-android` is only needed for projects with multiple `$(TargetFrameworks)`._
*NOTE: `-f net8.0-android` is only needed for projects with multiple `$(TargetFrameworks)`.*

Once the application is installed and started, `dotnet-trace` should show something similar to:

Expand All @@ -141,14 +196,8 @@ directory.

## How to get GC memory dumps?

If running on desktop, you can use the `dotnet-gcdump` global tool.
This can be installed via:

```dotnetcli
$ dotnet tool install --global dotnet-gcdump
```

To use it, for example:
If running on desktop, you can use the `dotnet-gcdump` global tool for
local processes. For example:

```sh
# `hw-readline` is a standard Hello World, with a `Console.ReadLine()` at the end
Expand All @@ -167,6 +216,7 @@ $ dotnet-gcdump collect -p 33972
Writing gcdump to '.../hw-readline/20230314_113922_33972.gcdump'...
Finished writing 5624131 bytes.
```

See the [`dotnet-gcdump` documentation][dotnet-gcdump]
for further details about its usage.

Expand All @@ -188,6 +238,9 @@ $ dotnet-gcdump collect -p 38604

This will create a `*.gcdump` file in the current directory.

Note that using `nosuspend` in the `debug.mono.profile` property is
useful, as it won't block application startup.

## Memory Dumps for Android in .NET 7

In .NET 7, we have to use th older, more complicated method for collecting
Expand Down Expand Up @@ -228,12 +281,11 @@ This saves a `foo.gcdump` that you can open in Visual Studio.
See the [dotnet/runtime documentation][gc-dumps-on-mono] for
additional details.

[dotnet-gcdump]: https://learn.microsoft.com/dotnet/core/diagnostics/dotnet-gcdump
[mono-events]: https://github.com/dotnet/runtime/blob/c887c92d8af4ce65b19962b777f96ae8eb997a42/src/coreclr/vm/ClrEtwAll.man#L7433-L7468
[dotnet-trace-help]: https://github.com/dotnet/diagnostics/blob/6d755e8b5435b1380c118e9d81e075654b0330c9/documentation/dotnet-trace-instructions.md#dotnet-trace-help
[gc-dumps-on-mono]: https://github.com/dotnet/runtime/blob/728fd85bc7ad04f5a0ea2ad0d4d8afe371ff9b64/docs/design/mono/diagnostics-tracing.md#collect-gc-dumps-on-monovm

## How to `dotnet trace` our build?
## How to `dotnet trace` a Build?

Setting this up is easy, the main issue is there end up being
potentially *a lot* of threads (30-40) depending on the build.
Expand Down
5 changes: 1 addition & 4 deletions LICENSE → LICENSE.TXT
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
Xamarin.Android SDK

The MIT License (MIT)

Copyright (c) .NET Foundation Contributors
Copyright (c) .NET Foundation and Contributors

All rights reserved.

Expand All @@ -23,4 +21,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

3 changes: 1 addition & 2 deletions build-tools/create-packs/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
<Target Name="_SetGlobalProperties">
<ItemGroup>
<_GlobalProperties Include="-p:Configuration=$(Configuration)" />
<_GlobalProperties Include="-p:NuGetLicense=$(NuGetLicense)" />
<_GlobalProperties Include="-p:IncludeSymbols=False" />
</ItemGroup>
</Target>
Expand Down Expand Up @@ -103,7 +102,7 @@
/>
<!-- The .nupkg contains the files under /data/, so we need to move them -->
<ItemGroup>
<_WLExtractedFiles Include="$(_SdkManifestsFolder)temp\LICENSE" />
<_WLExtractedFiles Include="$(_SdkManifestsFolder)temp\LICENSE.TXT" />
<_WLExtractedFiles Include="$(_SdkManifestsFolder)temp\data\*" />
</ItemGroup>
<Move SourceFiles="@(_WLExtractedFiles)" DestinationFolder="$(_SdkManifestsFolder)microsoft.net.sdk.android" />
Expand Down
6 changes: 3 additions & 3 deletions build-tools/create-packs/License.targets
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<!-- Ownership and LICENSE settings for .nupkg's -->
<!-- Ownership and LICENSE.TXT settings for .nupkg's -->
<Project>
<PropertyGroup>
<Authors>Microsoft</Authors>
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
<PackageProjectUrl>https://github.com/xamarin/xamarin-android</PackageProjectUrl>
<NuGetLicense Condition="Exists('$(XamarinAndroidSourcePath)external\monodroid\tools\scripts\License.txt')">$(XamarinAndroidSourcePath)external\monodroid\tools\scripts\License.txt</NuGetLicense>
<NuGetLicense Condition=" '$(NuGetLicense)' == '' ">$(XamarinAndroidSourcePath)LICENSE</NuGetLicense>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<NuGetLicense Condition=" '$(NuGetLicense)' == '' or '$(PackageId)' != 'Microsoft.Android.Sdk.$(HostOS)' ">$(XamarinAndroidSourcePath)LICENSE.TXT</NuGetLicense>
<PackageLicenseFile>LICENSE.TXT</PackageLicenseFile>
<BeforePack>_GetLicense;$(BeforePack)</BeforePack>
</PropertyGroup>
<Target Name="_GetLicense">
Expand Down
20 changes: 10 additions & 10 deletions eng/Version.Details.xml
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
<Dependencies>
<ProductDependencies>
<Dependency Name="Microsoft.Dotnet.Sdk.Internal" Version="9.0.100-preview.3.24126.2">
<Dependency Name="Microsoft.Dotnet.Sdk.Internal" Version="9.0.100-preview.3.24153.2">
<Uri>https://github.com/dotnet/installer</Uri>
<Sha>d070660282eb5f78497310f77093638744112e03</Sha>
<Sha>893b762b6e36d558df7ae6fccdfd8034f83a1c2e</Sha>
</Dependency>
<Dependency Name="Microsoft.NET.ILLink.Tasks" Version="9.0.0-preview.2.24123.1" CoherentParentDependency="Microsoft.Dotnet.Sdk.Internal">
<Dependency Name="Microsoft.NET.ILLink.Tasks" Version="9.0.0-preview.3.24129.2" CoherentParentDependency="Microsoft.Dotnet.Sdk.Internal">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>99b76018b6e4edc4ce185dd5f3c5697c6941d88e</Sha>
<Sha>5e603d595e63ddc5cdce9777a40608279abdcc37</Sha>
</Dependency>
<Dependency Name="Microsoft.NETCore.App.Ref" Version="9.0.0-preview.2.24123.1" CoherentParentDependency="Microsoft.Dotnet.Sdk.Internal">
<Dependency Name="Microsoft.NETCore.App.Ref" Version="9.0.0-preview.3.24129.2" CoherentParentDependency="Microsoft.Dotnet.Sdk.Internal">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>99b76018b6e4edc4ce185dd5f3c5697c6941d88e</Sha>
<Sha>5e603d595e63ddc5cdce9777a40608279abdcc37</Sha>
</Dependency>
<Dependency Name="Microsoft.NET.Workload.Emscripten.Current.Manifest-9.0.100.Transport" Version="9.0.0-preview.2.24121.1" CoherentParentDependency="Microsoft.NETCore.App.Ref">
<Dependency Name="Microsoft.NET.Workload.Emscripten.Current.Manifest-9.0.100.Transport" Version="9.0.0-preview.3.24126.1" CoherentParentDependency="Microsoft.NETCore.App.Ref">
<Uri>https://github.com/dotnet/emsdk</Uri>
<Sha>2d3f1fe4807a21879cedba9d3fde8cd329fb17f2</Sha>
<Sha>0f3e462442af5fe65271e3185d5b645ad40a6041</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Cecil" Version="0.11.4-alpha.24119.1" CoherentParentDependency="Microsoft.NET.ILLink.Tasks">
<Dependency Name="Microsoft.DotNet.Cecil" Version="0.11.4-alpha.24120.1" CoherentParentDependency="Microsoft.NET.ILLink.Tasks">
<Uri>https://github.com/dotnet/cecil</Uri>
<Sha>61250b0ed403b3f9b69a33f7d8f66f311338d6a1</Sha>
<Sha>0d0bc8e0f47fdae9834e1eac678f364c50946133</Sha>
</Dependency>
</ProductDependencies>
<ToolsetDependencies>
Expand Down
10 changes: 5 additions & 5 deletions eng/Versions.props
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<Project>
<!--Package versions-->
<PropertyGroup>
<MicrosoftDotnetSdkInternalPackageVersion>9.0.100-preview.3.24126.2</MicrosoftDotnetSdkInternalPackageVersion>
<MicrosoftNETILLinkTasksPackageVersion>9.0.0-preview.2.24123.1</MicrosoftNETILLinkTasksPackageVersion>
<MicrosoftNETCoreAppRefPackageVersion>9.0.0-preview.2.24123.1</MicrosoftNETCoreAppRefPackageVersion>
<MicrosoftDotnetSdkInternalPackageVersion>9.0.100-preview.3.24153.2</MicrosoftDotnetSdkInternalPackageVersion>
<MicrosoftNETILLinkTasksPackageVersion>9.0.0-preview.3.24129.2</MicrosoftNETILLinkTasksPackageVersion>
<MicrosoftNETCoreAppRefPackageVersion>9.0.0-preview.3.24129.2</MicrosoftNETCoreAppRefPackageVersion>
<MicrosoftDotNetApiCompatPackageVersion>7.0.0-beta.22103.1</MicrosoftDotNetApiCompatPackageVersion>
<MicrosoftDotNetBuildTasksFeedPackageVersion>7.0.0-beta.22103.1</MicrosoftDotNetBuildTasksFeedPackageVersion>
<MicrosoftNETWorkloadEmscriptenCurrentManifest90100TransportVersion>9.0.0-preview.2.24121.1</MicrosoftNETWorkloadEmscriptenCurrentManifest90100TransportVersion>
<MicrosoftNETWorkloadEmscriptenCurrentManifest90100TransportVersion>9.0.0-preview.3.24126.1</MicrosoftNETWorkloadEmscriptenCurrentManifest90100TransportVersion>
<MicrosoftNETWorkloadEmscriptenPackageVersion>$(MicrosoftNETWorkloadEmscriptenCurrentManifest90100TransportVersion)</MicrosoftNETWorkloadEmscriptenPackageVersion>
<MicrosoftTemplateEngineTasksPackageVersion>7.0.100-rc.1.22410.7</MicrosoftTemplateEngineTasksPackageVersion>
<MicrosoftDotNetCecilPackageVersion>0.11.4-alpha.24119.1</MicrosoftDotNetCecilPackageVersion>
<MicrosoftDotNetCecilPackageVersion>0.11.4-alpha.24120.1</MicrosoftDotNetCecilPackageVersion>
<SystemIOHashingPackageVersion>$(MicrosoftNETCoreAppRefPackageVersion)</SystemIOHashingPackageVersion>
</PropertyGroup>
<PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion external/Java.Interop
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "http://json.schemastore.org/template",
"author": "Microsoft",
"classifications": [ "Android", "Mobile" ],
"name": "Android Activity template",
"name": "Android Activity",
"description": "An Android Activity class",
"tags": {
"language": "C#",
Expand Down
Loading

0 comments on commit f85a6ae

Please sign in to comment.