-
Notifications
You must be signed in to change notification settings - Fork 535
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Xamarin.Android.Build.Tasks] Profiled AOT can Full AOT the main asse…
…mbly (#6482) When using the built-in profiles for Profiled AOT, one drawback is the user's code isn't AOT'd. We only AOT types that are called in the BCL, `Java.Interop.dll`, `Mono.Android.dll`, etc. To make this better, we can AOT the "main" assembly. Most code in the users' main assembly would likely get called on startup. This should have a minor impact to `.apk` size, but gain us a better startup boost by default. When testing, I can see more methods AOT'd: 11-11 09:01:01.441 16386 16386 D Mono : AOT: FOUND method foo.MainActivity:OnCreate (Android.OS.Bundle) [0x7c050e8e20f0 - 0x7c050e8e213b 0x7c050e8e2673] ~~ Results ~~ | Test | File Size (Δ) | Activity Displayed (Δ) | | ------------------------------------- | ----------------: | ------------------------: | | `dotnet new android` w/o AOT app | -baseline- | 193ms | | `dotnet new android` *with* AOT app | (0%) | 192ms (99%) | | `dotnet new maui` w/o AOT app | -baseline- | 641ms | | `dotnet new maui` *with* AOT app | +20,480 (0.14%) | 627ms (98%) | The `dotnet new android` app is built with: > dotnet build -c Release -p:AndroidEnableProfiledAot=true -p:RunAOTCompilation=true -r android-arm64 -p:AndroidPackageFormat=apk File size differences: > apkdiff -f before.apk after.apk Size difference in bytes ([*1] apk1 only, [*2] apk2 only): + 5,632 lib/arm64-v8a/libaot-foo.dll.so + 5 assemblies/assemblies.blob Summary: + 5 Other entries 0.00% (of 787,048) + 0 Dalvik executables 0.00% (of 345,340) + 5,632 Shared libraries 0.09% (of 6,008,168) + 0 Package size difference 0.00% (of 3,169,571) 10 runs on a Pixel 5 was an average of 193ms before, and 192ms after (the `Activity Displayed` time). There may not, in fact, be a difference for `dotnet new android`. Next I installed .NET MAUI 6.0.101-preview.11.2149, and tried a `dotnet new maui` app: File size: > apkdiff -f before.apk after.apk Size difference in bytes ([*1] apk1 only, [*2] apk2 only): + 67,144 lib/arm64-v8a/libaot-foo.dll.so Summary: + 0 Other entries 0.00% (of 7,765,174) + 0 Dalvik executables 0.00% (of 6,443,152) + 67,144 Shared libraries 0.50% (of 13,388,688) + 20,480 Package size difference 0.14% (of 14,272,332) Total file size difference: --14,251,852 ++14,272,332 The average over 10 runs on a Pixel 5, before applying this change, is ~641ms. After applying this change, it's ~627ms. I think this might help startup by ~14ms in a `dotnet new maui` app. It would likely improve more depending on the app.
- Loading branch information
1 parent
f3de57d
commit 8ac4425
Showing
6 changed files
with
108 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
using System.IO; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Microsoft.Android.Build.Tasks; | ||
using Xamarin.Android.Tools; | ||
|
||
namespace Xamarin.Android.Tasks | ||
{ | ||
/// <summary> | ||
/// Called in .NET 6+ to populate %(AotArguments) metadata in the ResolvedAssemblies [Output] property. | ||
/// </summary> | ||
public class GetAotAssemblies : GetAotArguments | ||
{ | ||
public override string TaskPrefix => "GAOT"; | ||
|
||
public override Task RunTaskAsync () | ||
{ | ||
NdkTools? ndk = NdkTools.Create (AndroidNdkDirectory, Log); | ||
if (ndk == null) { | ||
return Task.CompletedTask; // NdkTools.Create will log appropriate error | ||
} | ||
|
||
bool hasValidAotMode = GetAndroidAotMode (AndroidAotMode, out AotMode); | ||
if (!hasValidAotMode) { | ||
LogCodedError ("XA3002", Properties.Resources.XA3002, AndroidAotMode); | ||
return Task.CompletedTask; | ||
} | ||
|
||
if (AotMode == AotMode.Interp) { | ||
LogDebugMessage ("Interpreter AOT mode enabled"); | ||
return Task.CompletedTask; | ||
} | ||
|
||
TryGetSequencePointsMode (AndroidSequencePointsMode, out SequencePointsMode); | ||
|
||
SdkBinDirectory = MonoAndroidHelper.GetOSBinPath (); | ||
|
||
var abi = AndroidRidAbiHelper.RuntimeIdentifierToAbi (RuntimeIdentifier); | ||
if (string.IsNullOrEmpty (abi)) { | ||
Log.LogCodedError ("XA0035", Properties.Resources.XA0035, RuntimeIdentifier); | ||
return Task.CompletedTask; | ||
} | ||
|
||
(_, string outdir, string mtriple, AndroidTargetArch arch) = GetAbiSettings (abi); | ||
string toolPrefix = GetToolPrefix (ndk, arch, out int level); | ||
|
||
var aotOptions = GetAotOptions (ndk, arch, level, outdir, mtriple, toolPrefix); | ||
|
||
var aotProfiles = new StringBuilder (); | ||
if (Profiles != null && Profiles.Length > 0) { | ||
aotProfiles.Append (",profile-only"); | ||
foreach (var p in Profiles) { | ||
var fp = Path.GetFullPath (p.ItemSpec); | ||
aotProfiles.Append (",profile="); | ||
aotProfiles.Append (fp); | ||
} | ||
} | ||
|
||
var arguments = string.Join (",", aotOptions); | ||
foreach (var assembly in ResolvedAssemblies) { | ||
var temp = Path.GetFullPath (Path.Combine (outdir, Path.GetFileNameWithoutExtension (assembly.ItemSpec))); | ||
Directory.CreateDirectory (temp); | ||
if (Path.GetFileNameWithoutExtension (assembly.ItemSpec) == TargetName) { | ||
LogDebugMessage ($"Not using profile(s) for main assembly: {assembly.ItemSpec}"); | ||
assembly.SetMetadata ("AotArguments", $"{arguments},temp-path={temp}"); | ||
} else { | ||
assembly.SetMetadata ("AotArguments", $"{arguments},temp-path={temp}{aotProfiles}"); | ||
} | ||
} | ||
|
||
return Task.CompletedTask; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters