Skip to content
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

[Xamarin.Android.Build.Tasks] Profiled AOT can Full AOT the main assembly #6482

Merged

Conversation

jonathanpeppers
Copy link
Member

@jonathanpeppers jonathanpeppers commented Nov 11, 2021

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 full AOT the "main" assembly. Most code in
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

A dotnet new android app, built with:

> dotnet build -c Release -p:AndroidEnableProfiledAot=true -p:RunAOTCompilation=true -r android-arm64 -p:AndroidPackageFormat=apk

File size:

> 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, in fact, not 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)

10 runs on a Pixel 5:

Before:
Activity: Displayed     656ms
Activity: Displayed     635ms
Activity: Displayed     623ms
Activity: Displayed     633ms
Activity: Displayed     660ms
Activity: Displayed     655ms
Activity: Displayed     634ms
Activity: Displayed     646ms
Activity: Displayed     628ms
Activity: Displayed     646ms
Activity: Displayed     630ms
-------------------------------
Average                 641ms

After:
Activity: Displayed     679ms
Activity: Displayed     644ms
Activity: Displayed     607ms
Activity: Displayed     620ms
Activity: Displayed     623ms
Activity: Displayed     615ms
Activity: Displayed     619ms
Activity: Displayed     623ms
Activity: Displayed     617ms
Activity: Displayed     631ms
Activity: Displayed     623ms
-------------------------------
Average                 627ms

I think this might help startup by ~14ms in a dotnet new maui app.
It would likely improve more depending on the app.

…mbly

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 full AOT the "main" assembly. Most code in
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 ~~

A `dotnet new android` app, built with:

    > dotnet build -c Release -p:AndroidEnableProfiledAot=true -p:RunAOTCompilation=true -r android-arm64 -p:AndroidPackageFormat=apk

File size:

    > 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, in fact, not 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)

10 runs on a Pixel 5:

    Before:
    Activity: Displayed     656ms
    Activity: Displayed     635ms
    Activity: Displayed     623ms
    Activity: Displayed     633ms
    Activity: Displayed     660ms
    Activity: Displayed     655ms
    Activity: Displayed     634ms
    Activity: Displayed     646ms
    Activity: Displayed     628ms
    Activity: Displayed     646ms
    Activity: Displayed     630ms
    ----------------------------------------------------------------
    Average                 641ms

    After:
    Activity: Displayed     679ms
    Activity: Displayed     644ms
    Activity: Displayed     607ms
    Activity: Displayed     620ms
    Activity: Displayed     623ms
    Activity: Displayed     615ms
    Activity: Displayed     619ms
    Activity: Displayed     623ms
    Activity: Displayed     617ms
    Activity: Displayed     631ms
    Activity: Displayed     623ms
    ----------------------------------------------------------------
    Average                 627ms

I think this might help startup by ~14ms in a `dotnet new maui` app.
It would likely improve more depending on the app.
@jonathanpeppers jonathanpeppers marked this pull request as ready for review November 12, 2021 20:05
@jonpryor
Copy link
Member

jonpryor commented Nov 16, 2021

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.

@jonathanpeppers jonathanpeppers merged commit 8ac4425 into dotnet:main Nov 16, 2021
@jonathanpeppers jonathanpeppers deleted the profiled-aot-main-assembly branch November 16, 2021 14:28
@github-actions github-actions bot locked and limited conversation to collaborators Jan 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants