Skip to content

Commit 73a20a6

Browse files
[One .NET] built-in Profiled AOT support
Fixes: dotnet#6053 This enables the ability to set: <PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <RunAOTCompilation>true</RunAOTCompilation> <AndroidEnableProfiledAot>true</AndroidEnableProfiledAot> </PropertyGroup> And a default `dotnet.aotprofile` will be passed to the `<MonoAOTCompiler/>` MSBuild task. There will not be a way to "record" profiles in the Android workload in .NET 6. This is because it relies on legacy Mono infrastructure that is not implemented in .NET 6. I created a Github repo for recording profiles, where I committed the necessary binaries such as `aprofutil` and `libmono-profiler-aot.so`: https://github.com/jonathanpeppers/android-profiled-aot I recorded a `dotnet.aotprofile` with the contents: Modules: 6799590C-2963-4835-AEDC-20C67D875132 System.Private.CoreLib 2CC403AF-60DC-48A9-9B69-FF254277AEA0 Mono.Android 92FF7068-2EA9-4681-B340-44E91077417A Java.Interop 008C0F24-5014-4D41-AAB9-DDFCEA59E171 Xamarin.Google.Android.Material 7CEE6098-BE9F-4043-B35A-B8B0684EF0CB Xamarin.AndroidX.AppCompat 20D1FBB8-829A-4618-8E82-8047C8827EA8 Xamarin.AndroidX.Fragment CC363D7A-9CDB-4999-9E10-279412B14A1B Xamarin.AndroidX.Activity 21CF52B7-0256-4838-848C-DA026B2F1789 Xamarin.AndroidX.Core D1DE5607-BC27-45FC-93EC-0542C787E5FF Xamarin.AndroidX.DrawerLayout Summary: Modules: 9 Types: 229 Methods: 1,010 `AndroidApp1` is the `Navigation Drawer App` template from "legacy" Xamarin.Android. I ported this template to .NET 6 and dropped usage of Xamarin.Essentials. I thought this was a good target for a default profile, because of its heavy usage of AndroidX and Google Material. In a future PR, I will add a default AOT profile for .NET MAUI to be shipped inside the `maui` workload. ~~ Results ~~ All tests: 1. Were running on a [Google Pixel 5][0], and 2. Enabled two architectures, arm64 and x86, and 3. **JIT time** was average of 10 runs with `-c Release`, no AOT 4. **AOT time** was average of 10 runs with `-c Release -p:RunAOTCompilation=true`, with the`Activity: Displayed` time 5. **Profiled AOT time** was average of 10 runs with `-c Release -p:RunAOTCompilation=true -p:AndroidEnableProfiledAot=true` with the `Activity: Displayed` time. | Test | JIT time | AOT time | Profiled AOT time | JIT apk size | AOT apk size | Profiled AOT apk size | | ------------------ | ----------: | ----------: | ----------------: | ------------: | ------------: | --------------------: | | [AndroidApp1][1] | 00:00.4387 | 00:00:3317 | 00:00.3093 | 9,155,954 | 12,755,672 | 9,777,880 | | [MauiApp1][2] | 00:01.4205 | 00:00:7285 | 00:00.7098 | 17,435,225 | 44,751,651 | 23,210,787 | [0]: store.google.com/us/product/pixel_5_specs?hl=en-US [1]: jonathanpeppers/android-profiled-aot@e48c6df/AndroidApp1 [2]: jonathanpeppers/android-profiled-aot@e48c6df/MauiApp1
1 parent e9a4c9f commit 73a20a6

File tree

6 files changed

+63
-2
lines changed

6 files changed

+63
-2
lines changed

build-tools/create-packs/Microsoft.Android.Sdk.proj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ core workload SDK packs imported by WorkloadManifest.targets.
7676
<_PackageFiles Include="$(XamarinAndroidSourcePath)src\Xamarin.Android.Build.Tasks\Microsoft.Android.Sdk\Sdk\**" PackagePath="Sdk" />
7777
<_PackageFiles Include="$(XamarinAndroidSourcePath)src\Microsoft.Android.Sdk.ILLink\PreserveLists\**" PackagePath="PreserveLists" />
7878
<_PackageFiles Include="$(XamarinAndroidSourcePath)src\Xamarin.Android.Build.Tasks\Microsoft.Android.Sdk\targets\**" PackagePath="targets" />
79+
<_PackageFiles Include="$(XamarinAndroidSourcePath)src\Xamarin.Android.Build.Tasks\dotnet.aotprofile" PackagePath="targets" />
7980
<_PackageFiles Include="$(IntermediateOutputPath)UnixFilePermissions.xml" PackagePath="data" Condition=" '$(HostOS)' != 'Windows' " />
8081
<None Include="$(MSBuildThisFileDirectory)SignList.xml" CopyToOutputDirectory="PreserveNewest" />
8182
</ItemGroup>

src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Aot.targets

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,13 @@ They run in a context of an inner build with a single $(RuntimeIdentifier).
6969
TempDirectory="$([MSBuild]::EnsureTrailingSlash($(_AotOutputDirectory)))%(FileName)"
7070
AotArguments="$(_AotArguments),temp-path=$([System.IO.Path]::GetFullPath(%(_MonoAOTAssemblies.TempDirectory)))"
7171
/>
72+
<AndroidAotProfile Include="$(MSBuildThisFileDirectory)dotnet.aotprofile" Condition=" '$(AndroidEnableProfiledAot)' == 'true' and '$(AndroidUseDefaultAotProfile)' != 'false' " />
7273
</ItemGroup>
7374
<MakeDir Directories="$(IntermediateOutputPath)aot\;@(_MonoAOTAssemblies->'%(TempDirectory)')" />
7475
<MonoAOTCompiler
7576
Assemblies="@(_MonoAOTAssemblies)"
7677
CompilerBinaryPath="$(_MonoAOTCompilerPath)"
78+
AotProfilePath="@(AndroidAotProfile->'%(FullPath)')"
7779
DisableParallelAot="$(_DisableParallelAot)"
7880
LibraryFormat="So"
7981
Mode="$(AndroidAotMode)"

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Application.targets

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ Copyright (C) 2019 Microsoft Corporation. All rights reserved.
4848
DependsOnTargets="$(_BeginAotProfilingDependsOnTargets)">
4949
</Target>
5050
<Target Name="FinishAotProfiling"
51-
DependsOnTargets="_ResolveSdks">
51+
DependsOnTargets="_ResolveSdks;_ResolveMonoAndroidSdks">
5252
<Exec Command="&quot;$(AdbToolPath)adb&quot; $(AdbTarget) forward tcp:$(AndroidAotProfilerPort) tcp:$(AndroidAotProfilerPort)" />
53-
<Exec Command="&quot;$(MonoAndroidBinDirectory)aprofutil&quot; $(AProfUtilExtraOptions) -s -v -p $(AndroidAotProfilerPort) -o &quot;$(AndroidAotCustomProfilePath)&quot;" />
53+
<Exec Command="&quot;$(AProfUtilToolPath)aprofutil&quot; $(AProfUtilExtraOptions) -s -v -p $(AndroidAotProfilerPort) -o &quot;$(AndroidAotCustomProfilePath)&quot;" />
5454
</Target>
5555
</Project>

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,11 @@ because xbuild doesn't support framework reference assemblies.
727727
/>
728728
</CreateProperty>
729729

730+
<!-- We should slowly port all the <CreateProperty/> calls to <PropertyGroup/> here -->
731+
<PropertyGroup>
732+
<AProfUtilToolPath Condition=" '$(AProfUtilToolPath)' == '' ">$(MonoAndroidBinDirectory)</AProfUtilToolPath>
733+
</PropertyGroup>
734+
730735
<!-- Get the defined constants for this API Level -->
731736
<GetAndroidDefineConstants AndroidApiLevel="$(_AndroidApiLevel)" ProductVersion="$(MonoAndroidVersion)">
732737
<Output TaskParameter="AndroidDefineConstants" ItemName="AndroidDefineConstants" />
Binary file not shown.

src/monodroid/jni/monodroid-glue.cc

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,59 @@ MonodroidRuntime::set_profile_options ()
15841584

15851585
// setenv(3) makes copies of its arguments
15861586
setenv ("DOTNET_DiagnosticPorts", value.get (), 1);
1587+
1588+
constexpr char OUTPUT_ARG[] = "output=";
1589+
constexpr size_t OUTPUT_ARG_LEN = sizeof(OUTPUT_ARG) - 1;
1590+
1591+
ssize_t colon_idx = value.index_of (':');
1592+
size_t start_index = colon_idx < 0 ? 0 : static_cast<size_t>(colon_idx + 1);
1593+
dynamic_local_string<SENSIBLE_PATH_MAX> output_path;
1594+
bool have_output_arg = false;
1595+
string_segment param;
1596+
1597+
while (value.next_token (start_index, ',', param)) {
1598+
dynamic_local_string<SENSIBLE_PATH_MAX> temp;
1599+
temp.assign (param.start (), param.length ());
1600+
if (!param.starts_with (OUTPUT_ARG) || param.length () == OUTPUT_ARG_LEN) {
1601+
continue;
1602+
}
1603+
1604+
output_path.assign (param.start () + OUTPUT_ARG_LEN, param.length () - OUTPUT_ARG_LEN);
1605+
have_output_arg = true;
1606+
break;
1607+
}
1608+
1609+
if (!have_output_arg) {
1610+
constexpr char AOT_EXT[] = "aotprofile";
1611+
constexpr char AOT_PREFIX[] = "aot:";
1612+
constexpr size_t AOT_PREFIX_LENGTH = sizeof(AOT_PREFIX) - 1;
1613+
constexpr char PROFILE_FILE_NAME_PREFIX[] = "profile.";
1614+
1615+
size_t length_adjust = colon_idx >= 1 ? 0 : 1;
1616+
1617+
output_path
1618+
.assign_c (androidSystem.get_override_dir (0))
1619+
.append (MONODROID_PATH_SEPARATOR)
1620+
.append (PROFILE_FILE_NAME_PREFIX);
1621+
1622+
if (value.starts_with (AOT_PREFIX, AOT_PREFIX_LENGTH - length_adjust)) {
1623+
output_path.append (AOT_EXT);
1624+
} else {
1625+
size_t len = colon_idx < 0 ? value.length () : static_cast<size_t>(colon_idx + 1);
1626+
output_path.append (value.get (), len);
1627+
}
1628+
1629+
if (colon_idx < 0)
1630+
value.append (":");
1631+
else
1632+
value.append (",");
1633+
value
1634+
.append (OUTPUT_ARG)
1635+
.append (output_path.get (), output_path.length ());
1636+
}
1637+
1638+
log_warn (LOG_DEFAULT, "Initializing profiler with options: %s", value.get ());
1639+
debug.monodroid_profiler_load (androidSystem.get_runtime_libdir (), value.get (), output_path.get ());
15871640
}
15881641
#else // def NET6
15891642
inline void

0 commit comments

Comments
 (0)