-
Notifications
You must be signed in to change notification settings - Fork 516
Profiling
See Profiling App Launch for information about how to profile the app's launch.
Note Only debug builds have profiling support enabled by default.
This document references the mlaunch
tool, the easiest way to get it is to
install Xamarin.iOS if you don't have it installed already. Latest package as
of this writing: xamarin.ios-15.10.0.5.pkg.
Once installed, the mlaunch
tool can be found here:
/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/bin/mlaunch
The mlaunch
tool is also installed with the iOS workload for .NET, but the
location on disk depends on the actual version installed, so it's a bit harder
to find.
In any case, creating an alias will allow the instructions below to work:
alias mlaunch=/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/bin/mlaunch
Otherwise replace mlaunch
with the full path according to the location on
disk on your system.
We need the dotnet-dsrouter
and dotnet-trace
tools, so let's install them:
$ dotnet tool install --global dotnet-dsrouter
$ dotnet tool install --global dotnet-trace
Note This pull request for
dotnet-dsrouter
is required for profiling on device to work: https://github.com/dotnet/diagnostics/pull/3134
-
The first step is to launch the tool that provides a connection between the app and the .NET tracing tools:
$ dotnet-dsrouter client-server -ipcc ~/my-sim-port -tcps 127.0.0.1:9000
-
Launch the app and make it suspend upon launch (waiting for the .NET tooling to connect):
$ mlaunch --launchsim bin/Debug/net*/*/*.app --device :v2:runtime=com.apple.CoreSimulator.SimRuntime.iOS-15-4,devicetype=com.CoreSimulator.SimDeviceType.iPhone-11 --wait-for-exit --stdout=$(tty) --stderr=$(tty) --argument --connection-mode --argument none '--setenv:DOTNET_DiagnosticPorts=127.0.0.1:9000,suspend'
-
At this point it's necessary to wait until the following line shows up in the terminal:
The runtime has been configured to pause during startup and is awaiting a Diagnostics IPC ResumeStartup command from a Diagnostic Port
-
Once that's printed, go ahead and start profiling:
$ dotnet-trace collect --diagnostic-port ~/my-sim-port --format speedscope
Execute the following to get the list of all available simulators on your machine:
$ xcrun simctl list devices
== Devices ==
-- iOS 12.4 --
iPhone 6 (iOS 12.4) (C49E6049-5F51-40BB-833A-1B36C4EB95A6) (Booted)
-- iOS 16.0 --
iPhone X (iOS 16.0) (50BCC90D-7E56-4AFB-89C5-3688BF345998) (Booted)
iPhone SE (3rd generation) - iOS 16.0 (BE619DC5-F728-4E2F-9425-4731778A78FC) (Shutdown)
iPad Air (5th generation) - iOS 16.0 (E6C465F0-43E5-4066-A2E9-D293254CBD30) (Shutdown)
-- tvOS 16.0 --
Apple TV (tvOS 16.0) (ED020B77-8E3D-4BB7-B7D7-E94ECCCD62BE) (Shutdown)
-- watchOS 6.0 --
Apple Watch Series 3 - 38mm (watchOS 6.0) (BB2AB52D-803B-42EA-A456-66ACBF90DF25) (Booted)
-- watchOS 9.0 --
Apple Watch Series 7 - 41mm (watchOS 9.0) (2FAEA489-CD7F-42D9-9488-9B21858BB30F) (Booted)
Then pick an applicable device, and copy the UDID (50BCC90D-7E56-4AFB-89C5-3688BF345998
would be an example here), and pass the following to mlaunch
:
$ mlaunch ... --device :v2:udid=50BCC90D-7E56-4AFB-89C5-3688BF345998 ...
It's also possible to specify a runtime/devicetype combination; the valid values can be queried with simctl
like this:
$ xcrun simctl list devicetypes
== Device Types ==
iPhone 4s (com.apple.CoreSimulator.SimDeviceType.iPhone-4s)
iPhone 5 (com.apple.CoreSimulator.SimDeviceType.iPhone-5)
iPhone 5s (com.apple.CoreSimulator.SimDeviceType.iPhone-5s)
iPhone 6 Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-6-Plus)
iPhone 6 (com.apple.CoreSimulator.SimDeviceType.iPhone-6)
iPhone 6s (com.apple.CoreSimulator.SimDeviceType.iPhone-6s)
iPhone 6s Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-6s-Plus)
iPhone SE (1st generation) (com.apple.CoreSimulator.SimDeviceType.iPhone-SE)
iPhone 7 (com.apple.CoreSimulator.SimDeviceType.iPhone-7)
iPhone 7 Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-7-Plus)
iPhone 8 (com.apple.CoreSimulator.SimDeviceType.iPhone-8)
iPhone 8 Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-8-Plus)
iPhone X (com.apple.CoreSimulator.SimDeviceType.iPhone-X)
iPhone Xs (com.apple.CoreSimulator.SimDeviceType.iPhone-XS)
[...]
and
$ xcrun simctl list runtimes available
== Runtimes ==
iOS 12.4 (12.4 - 16G73) - com.apple.CoreSimulator.SimRuntime.iOS-12-4
iOS 13.5 (13.5 - 17F61) - com.apple.CoreSimulator.SimRuntime.iOS-13-5
iOS 15.4 (15.4 - 19E240) - com.apple.CoreSimulator.SimRuntime.iOS-15-4
tvOS 12.4 (12.4 - 16M567) - com.apple.CoreSimulator.SimRuntime.tvOS-12-4
tvOS 15.4 (15.4 - 19L439) - com.apple.CoreSimulator.SimRuntime.tvOS-15-4
tvOS 16.0 (16.0 - 20J5299n) - com.apple.CoreSimulator.SimRuntime.tvOS-16-0
tvOS 16.0 (16.0 - 20J5319f) - com.apple.CoreSimulator.SimRuntime.tvOS-16-0
watchOS 6.0 (6.0 - 17R575) - com.apple.CoreSimulator.SimRuntime.watchOS-6-0
watchOS 6.2 (6.2.1 - 17T531) - com.apple.CoreSimulator.SimRuntime.watchOS-6-2
watchOS 8.5 (8.5 - 19T241) - com.apple.CoreSimulator.SimRuntime.watchOS-8-5
watchOS 9.0 (9.0 - 20R5287q) - com.apple.CoreSimulator.SimRuntime.watchOS-9-0
watchOS 9.0 (9.0 - 20R5307f) - com.apple.CoreSimulator.SimRuntime.watchOS-9-0
and then finally pass the selected values to mlaunch
like this:
$ mlaunch ... --device :v2:runtime=com.apple.CoreSimulator.SimRuntime.iOS-15-4,devicetype=com.CoreSimulator.SimDeviceType.iPhone-X ...
Note This pull request for
dotnet-dsrouter
is required for profiling on device to work: https://github.com/dotnet/diagnostics/pull/3134
The first step is to connect an iOS device to the Mac using a USB cable.
The process is very similar to the process for the simulator:
-
Launch the tool that bridges the app and the .NET tracing tools:
$ dotnet-dsrouter server-client -ipcs ~/my-dev-port -tcpc 127.0.0.1:9001 --forward-port iOS
Compared to the simulator, this:
- Adds
--forward-port iOS
- Changes the local ports, both client (
~/my-dev-port
vs~/my-sim-port
) and server (:9001
vs:9000
) - it's easier to debug any problems when using different ports.
- Adds
-
Install & launch the app and make it suspend upon launch:
$ mlaunch --installdev bin/Debug/net*/*/*.app --devname ... $ mlaunch --launchdev bin/Debug/net*/*/*.app --devname ... --wait-for-exit --argument --connection-mode --argument none '--setenv:DOTNET_DiagnosticPorts=127.0.0.1:9001,suspend,listen'
-
At this point it's necessary to wait until the following line shows up in the terminal:
The runtime has been configured to pause during startup and is awaiting a Diagnostics IPC ResumeStartup command from a Diagnostic Port
-
Once that's printed, go ahead and start profiling:
$ dotnet-trace collect --diagnostic-port ~/my-dev-port,connect --format speedscope
Profiling on the desktop (both macOS and Mac Catalyst apps are the same) is much easier.
-
Launch the executable, passing the
DOTNET_DiagnosticPorts
variable directly:$ DOTNET_DiagnosticPorts=~/my-desktop-port,suspend ./bin/Debug/net6.0-*/*/MyTestApp.app/Contents/MacOS/MyTestApp
-
At this point it's necessary to wait until the following line shows up in the terminal:
The runtime has been configured to pause during startup and is awaiting a Diagnostics IPC ResumeStartup command from a Diagnostic Port
-
Once that's printed, go ahead and start profiling:
$ dotnet-trace collect --diagnostic-port ~/my-desktop-port --format speedscope
In this guide I've selected to save the profiling results as speedscope files. These can be viewed in various ways, for instance online at https://speedscope.app.
- README
- xcode13.0 Binding Status
- xcode13.1 Binding Status
- xcode13.2 Binding Status
- xcode13.3 Binding Status
- xcode13.4 Binding Status
- xcode14.0 Binding Status
- xcode14.1 Binding Status
- xcode14.2 Binding Status
- xcode14.3 Binding Status
- xcode15.0 Binding Status
- xcode15.1 Binding Status
- xcode15.3 Binding Status
- xcode15.4 Binding Status
- xcode16.0 Binding Status
- xcode16.1 Binding Status
- xcode16.2 Binding Status