-
Notifications
You must be signed in to change notification settings - Fork 383
Extend dotnet-gcdump support for mobile and dotnet-dsrouter scenarios. #4081
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extend dotnet-gcdump support for mobile and dotnet-dsrouter scenarios. #4081
Conversation
08ca6e1 to
56b77df
Compare
56b77df to
f4a5528
Compare
|
One option that could be looked into is instead of having the user manually specify the --dsrouter argument to tools like gcdump, trace, counter ect to connect to the dsrouter default IPC channel (when using -p), we could have the tools first evaluate if the process has setup the dsrouter specific IPC channel and pick that over the default, that way, there is no risk that users forgets to use --dsrouter and end up using the default IPC channel of dsrouter itself. Will look into change using that pattern for this PR. |
7abd780 to
ddedef5
Compare
|
Dropped the need for This greatly simplify the default dotnet-dsrouter use case since dotnet-dsrouter can now be started without a named IPC channel and all diagnostic tooling can connect to the routed IPC channel using |
935e858 to
6405f16
Compare
6405f16 to
d0f0789
Compare
|
Looks like the -p scenario in dotnet-gcdump got lost when dropping the use of --dsrouter argument, will need to re-add that to the PR or dotnet-gcdump will ignore dumps since the pid of attached process (dotnet-dsrouter) won't match the pid in returned EventPipe events (pid of mobile process). |
a2edbf2 to
fd5c7e9
Compare
tommcdon
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this looks like a great step forward for mono diagnostic tooling. I scanned the code changes and nothing jumped out to me. I trust that the right level of validation was done against the code change, and so I am approving.
We should ensure we follow-up with documentation for the new command-line args and support, along with a new walkthrough.
dotnet-dsrouter can be a little hard to configure for mobile use cases since it needs a number of arguments, both to setup its local IPC client|server and the corresponding TCP client|server and what arguments to use depends on what mobile platform and scenario the user runs. There are currently a number of different scenarios described in different sources of documentation: Runtime docs: https://github.com/dotnet/runtime/blob/main/docs/design/mono/diagnostics-tracing.md iOS SDK docs: https://github.com/xamarin/xamarin-macios/wiki/Profiling Android SDK docs: https://github.com/xamarin/xamarin-android/blob/main/Documentation/guides/tracing.md They all fall into a number of predefined scenarios and a number of "default" parameters that should be used. This PR creates 4 new commands in dotnet-dsrouter to explicitly use the defaults described in the documentation, ios-sim, ios, android-emu, android. They all fallback to default IPC server listener for dsrouter and in order to make that simpler in use with diagnostic tooling, changes done in #4081 is also needed to simplify the process. So lets take an example form the docs, running an app on iOS simulator. Before this PR the following dsrouter command needs to be run: ``` dotnet-dsrouter client-server -ipcc ~/my-sim-port -tcps 127.0.0.1:9000 launch app with DOTNET_DiagnosticPorts=127.0.0.1:9000 dotnet-trace collect --diagnostic-port ~/my-sim-port --format speedscope ``` With this PR (and #4081) the above will look like: ``` dotnet-dsrouter ios-sim launch app with DOTNET_DiagnosticPorts=127.0.0.1:9000 dotnet-trace collect -p:<dsrouter pid> --format speedscope ``` dontet-dsrouter will output both its pid as well as what DOTNET_DiagnosticPorts that can be used to connect to it on startup. Using a different mobile platform/scenario, like android emulator is pretty much identical, just switch ios-sim to android-emu. dotnet-dsrouter will output the exact DOTNET_DiagnosticPorts that should be used with any of the configured scenarios.
|
@lateralusX can you share the example commands you ran for: #4081 (comment) I was trying this on an Android device:
I also tried to use the simplified My versions are: |
|
Here is what I'm doing (and it works) Versions: |
|
@tranb3r thank this got me working on an Android emulator. I think the @lateralusX I'm still not able to get some combination of the above on an Android device. Normally, an extra |
|
@lateralusX another issue I'm seeing is, I have a type like this: public partial class MyPage
{
~MyPage() => Console.WriteLine("~MyPage");The message never prints, which indicates a leak I want to fix. But the dump does not contain these objects. When I saw this scenario in .NET 7, I was able to diagnose with these instructions. And used Filip Navara's tool to convert to |
The simplest way to get going with updated dsrouter is to use the pre-configured profiles, so if you just run dotnet-dsrouter android-emu it will be setup in connect mode, and you can use the pid for dsrouter as the -p when running tools like dotnet-trace or dotnet-gcdump. If you run dotnet-dsrouter android, that will try to setup the default port reverse, but it will need to find the adb tooling, so tool needs to either find it using path, or you setup the ANDROID_SDK_ROOT env variable when launching dotnet-dsrouter to point to the root location of your android sdk. If it has issues to setup the port reverse it will be logged in the console. It is also possible to run the tools using full set of parameters as previously done, so all previous configurations should still work as they used to do. You can also run the port reverse command as a separate process, in that case you don't need to pass the --forward-port command to dotnet-dsrouter. @jonathanpeppers So to summarize, if you run the later version of dotnet-dsrouter supporting the preconfigured profiles, you should be able to run like this: Android emulator:
Android device:
If you need details on the mode you run and how you should setup the env variable, dotnet-dsrouter (7.0.451301) supports --info argument that will give you additional details. Also note that the preconfigured android profile uses tcp:9000 tcp:9000 for its port reverse so it doesn't use different ports as I believe you used in the past since its not really needed. But as long as you use the default profiles all that should be preconfigured. @jonathanpeppers Please let me know if the above doesn't work for you and if possible supply the -v trace output from dotnet-dsrouter when running. |
When looking at the linked issue (dotnet/maui#17726) it looks like you have the same behavior in both .net7 and .net8, you only have one instance of Page2 in the dump, correct? So the dumps looks similar in that case, the Page2 instance has actually been GC:ed as reported in the dump? |
|
@lateralusX for the "missing objects" / finalizer issue, I'll file an issue on dotnet/runtime, since it appears to happen in both .NET 7 and 8. For the new commands, is there a doc somewhere on these? I will test them out today, and update the READMEs in xamarin-android, but do we need customer-facing docs somewhere? |
Haven't got around adding any new documentation yet, except what was in the original PR's adding the commands into dotnet-dsrouter, #4090. |
Context: dotnet/diagnostics#4081 Context: dotnet/diagnostics#4090 Context: dotnet/runtime#88634 Context: dotnet/diagnostics#4337 Using the latest `dotnet-trace` tooling: > dotnet tool list -g Package Id Version Commands -------------------------------------------------------------------------------------- dotnet-dsrouter 7.0.447801 dotnet-dsrouter dotnet-gcdump 7.0.447801 dotnet-gcdump dotnet-trace 7.0.447801 dotnet-trace There is a simplified way to profile Android apps. For an Android emulator: > dotnet-dsrouter android-emu Start an application on android emulator with one of the following environment variables set: DOTNET_DiagnosticPorts=10.0.2.2:9000,nosuspend,connect DOTNET_DiagnosticPorts=10.0.2.2:9000,suspend,connect > adb shell setprop debug.mono.profile '10.0.2.2:9000,suspend,connect' > dotnet-trace ps 3248 dotnet-dsrouter > dotnet-trace collect -p 3248 ... [00:00:00:09] Recording trace 3.2522 (MB) Press <Enter> or <Ctrl+C> to exit... For an Android device you will eventually be able to do `dotnet-dsrouter android`, except we found one issue. Until dotnet/diagnostics#4337 is resolved, we can instead do: > adb reverse tcp:9000 tcp:9001 > dotnet-dsrouter server-server -tcps 127.0.0.1:9001 > adb shell setprop debug.mono.profile '127.0.0.1:9000,suspend,connect' > dotnet-trace ps > dotnet-trace collect -p 3248 We can also now use `dotnet-gcdump`! Instead of `dotnet-trace collect -p`, you can simply do: > dotnet-gcdump collect -p 3248 In both cases these tools *know* that the process ID is a `dotnet-dsrouter` process and to do the right thing.
Context: dotnet/diagnostics#4081 Context: dotnet/diagnostics#4090 Context: dotnet/runtime#88634 Context: dotnet/diagnostics#4337 Using the latest `dotnet-trace` tooling: > dotnet tool list -g Package Id Version Commands -------------------------------------------------------------------------------------- dotnet-dsrouter 7.0.447801 dotnet-dsrouter dotnet-gcdump 7.0.447801 dotnet-gcdump dotnet-trace 7.0.447801 dotnet-trace There is a simplified way to profile Android apps. For an Android emulator: > dotnet-dsrouter android-emu Start an application on android emulator with one of the following environment variables set: DOTNET_DiagnosticPorts=10.0.2.2:9000,nosuspend,connect DOTNET_DiagnosticPorts=10.0.2.2:9000,suspend,connect > adb shell setprop debug.mono.profile '10.0.2.2:9000,suspend,connect' > dotnet-trace ps 3248 dotnet-dsrouter > dotnet-trace collect -p 3248 ... [00:00:00:09] Recording trace 3.2522 (MB) Press <Enter> or <Ctrl+C> to exit... For an Android device you will eventually be able to do `dotnet-dsrouter android`, except we found one issue. Until dotnet/diagnostics#4337 is resolved, we can instead do: > adb reverse tcp:9000 tcp:9001 > dotnet-dsrouter server-server -tcps 127.0.0.1:9001 > adb shell setprop debug.mono.profile '127.0.0.1:9000,suspend,connect' > dotnet-trace ps > dotnet-trace collect -p 3248 We can also now use `dotnet-gcdump`! Instead of `dotnet-trace collect -p`, you can simply do: > dotnet-gcdump collect -p 3248 In both cases these tools *know* that the process ID is a `dotnet-dsrouter` process and to do the right thing.

.net8 adds support for dotnet-gcdump on Mono, meaning dotnet-gcdump will be used targeting mobile platforms. Currently dotnet-gcdump doesn't have support needed since it can only connect using pid or process name and has logic to make sure the process connected to has the same pid as the -p argument passed to dotnet-gcdump.
On mobile platforms, runtime is running on device and communicates using TCP/IP (over loopback interface, using Android adb port forwarding or usbmux on iOS). All logic related to communicate with devices on different platforms is handled by dotnet-dsrouter, that expose the same IPC channels as a normal runtime would do, meaning most diagnostic tools can connect to dotnet-dsrouter that will route all communication to/from device. Tools like dotnet-trace can leverage --diagnostic-port=,connect instead of pid to connect to a named IPC channel on dotnet-dsrouter (routed to a TCP/IP port on device). It is also possible to connect directly towards dotnet-dsrouters pid since it will masquerade like a regular runtime, but it will not alter the pid passed in EventPipe messages, meaning that dotnet.gcdump's pid checks currently breaks that scenario.
This PR extends diagnostic tooling support for mobile and dotnet-dsrouter scenarios.
Since support for dotnet-gcdump is included in .net8 runtime P7 it would be good to get these changes included in a diagnostic release available around the same time as .net8 p7.