Skip to content

Instantly share code, notes, and snippets.

@jonathanpeppers
Last active July 12, 2023 16:28
Show Gist options
  • Save jonathanpeppers/609298d8d5250194d5e64e1c0f197126 to your computer and use it in GitHub Desktop.
Save jonathanpeppers/609298d8d5250194d5e64e1c0f197126 to your computer and use it in GitHub Desktop.
Describing how I get .gcdump files from the Mono runtime

Part of the docs are here:

https://github.com/xamarin/xamarin-android/blob/main/Documentation/guides/tracing.md#how-to-get-gc-memory-dumps

But this expands on this, with a list of steps I do to profile .NET MAUI.

An overview:

  • Build & Run the Device Tests on Catalyst
  • Attach dotnet-trace with some settings
  • Run a memory-related test in the app, by clicking some UI
  • Convert the resulting .nettrace file to a .gcdump file
  • Open the .gcdump file in Visual Studio on Windows

I normally do this on Catalyst, just because the setup for dotnet-trace is easier (dotnet-dsrouter not needed). I end up with the same result as iOS mostly.

Once you've built MAUI, you can build the device tests:

$ ./bin/dotnet/dotnet build ~/src/maui/src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj -f net7.0-maccatalyst

Then launch the app with $DOTNET_DiagnosticPorts set:

$ DOTNET_DiagnosticPorts=~/my-dev-port,suspend ./src/Controls/tests/DeviceTests/bin/Debug/net7.0-maccatalyst/maccatalyst-x64/Microsoft.Maui.Controls.DeviceTests.app/Contents/MacOS/Microsoft.Maui.Controls.DeviceTests

Then launch dotnet-trace:

$ dotnet-trace collect --diagnostic-port ~/my-dev-port --providers Microsoft-DotNETRuntimeMonoProfiler:0xC900001:4

At this point, switch to the Device Tests app and click the UI to run a memory-related test.

After it fails, press enter to stop dotnet-trace. This will output a .nettrace file in the current directory.

I have a network share mounted on my Windows machine mounted at /Volumes/Shared/, so I actually run this:

$ dotnet-trace collect --diagnostic-port ~/my-dev-port --providers Microsoft-DotNETRuntimeMonoProfiler:0xC900001:4 -o /Volumes/Shared/my-dev-port-$(date +%s).nettrace

Then I move over to Windows to be able to open the .gcdump file in Visual Studio

I use a tool from Filip Navara:

https://github.com/filipnavara/mono-gcdump

Where I do dotnet run -- convert C:\Shared\my-dev-port.nettrace. It should output my-dev-port.gcdump you can open in Visual Studio.

@kcoop
Copy link

kcoop commented Jul 12, 2023

Very helpful script, thanks!

In my case after starting the app in suspend mode, I also needed to run an initial dotnet-trace without the --providers flag, the app crashed at startup otherwise.

After that, I was able to get convertible GC dumps with --providers Microsoft-DotNETRuntimeMonoProfiler:0xC900003:4

@jonathanpeppers
Copy link
Author

Ok yes, I do end up running dotnet-trace multiple times. One to get the app to launch as $DOTNET_DiagnosticPorts causes it to pause, Ctrl+C the first dotnet-trace, then do one later at the point I want to record a memory dump.

I think I normally use the same provider, though? 0xC900001:4

@kcoop
Copy link

kcoop commented Jul 12, 2023

I ran into this issue with that provider: filipnavara/mono-gcdump#6

@filipnavara's recommendation there worked, though I found I didn't need to add :heapcollect=ondemand.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment