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

See if we can use $(AndroidAotMode)=full MONO_AOT_MODE_FULL #9469

Open
jonathanpeppers opened this issue Oct 30, 2024 · 8 comments
Open

See if we can use $(AndroidAotMode)=full MONO_AOT_MODE_FULL #9469

jonathanpeppers opened this issue Oct 30, 2024 · 8 comments
Assignees
Labels
Area: App+Library Build Issues when building Library projects or Application projects. Area: App Runtime Issues in `libmonodroid.so`. enhancement Proposed change to current functionality.
Milestone

Comments

@jonathanpeppers
Copy link
Member

jonathanpeppers commented Oct 30, 2024

Android framework version

net9.0-android

Affected platform version

.NET 9 RC 2

Description

I was trying to enable "full AOT" and disable JIT on Android:

  • dotnet new maui - remove the other platforms beside Android
  • dotnet build build -c Release -p:AndroidAotMode=full -p:AndroidEnableProfiledAot=false -p:RunAOTCompilation=true -r android-arm64 -bl -t:Run

This should "AOT everything" and also toggle MONO_AOT_MODE_FULL at runtime.

This appears to pass the right flags to the <MonoAOTCompiler/> task:
Image

And at runtime:

10-30 08:58:14.982  9378  9378 D monodroid: Mono AOT mode: full
...
10-30 08:58:14.982  9378  9378 D monodroid: Probing for Mono AOT mode
10-30 08:58:14.982  9378  9378 D monodroid: Enabling AOT mode in Mono
10-30 08:58:14.982  9378  9378 D monodroid: Probing if we should use LLVM

mono_jit_set_aot_mode (mode);

But then the JIT is still used and we crash:

10-30 08:58:15.015  9378  9378 F mono-rt : [ERROR] FATAL UNHANDLED EXCEPTION: System.ExecutionEngineException: Attempting to JIT compile method '(wrapper other) void Java.Interop.JavaVMInterface:PtrToStructure (intptr,object)' while running in aot-only mode. See https://learn.microsoft.com/xamarin/ios/internals/limitations for more information.
10-30 08:58:15.015  9378  9378 F mono-rt : 
10-30 08:58:15.015  9378  9378 F mono-rt :    at System.Runtime.InteropServices.Marshal.PtrToStructure[JavaVMInterface](IntPtr )
10-30 08:58:15.015  9378  9378 F mono-rt :    at Java.Interop.JniRuntime.CreateInvoker(IntPtr )
10-30 08:58:15.015  9378  9378 F mono-rt :    at Java.Interop.JniRuntime..ctor(CreationOptions )
10-30 08:58:15.015  9378  9378 F mono-rt :    at Android.Runtime.AndroidRuntime..ctor(IntPtr , IntPtr , IntPtr , IntPtr , Boolean )
10-30 08:58:15.015  9378  9378 F mono-rt :    at Android.Runtime.JNIEnvInit.Initialize(JnienvInitializeArgs* )

Perhaps it fails on the first generic method?

Steps to Reproduce

See above.

Did you find any workaround?

No.

Relevant log output

aot-mode-full.txt

@jonathanpeppers jonathanpeppers added Area: App Runtime Issues in `libmonodroid.so`. Area: App+Library Build Issues when building Library projects or Application projects. labels Oct 30, 2024
@jonathanpeppers jonathanpeppers added this to the .NET 10 milestone Oct 30, 2024
@dotnet-policy-service dotnet-policy-service bot added the needs-triage Issues that need to be assigned. label Oct 30, 2024
@jonathanpeppers
Copy link
Member Author

@jpobst jpobst removed the needs-triage Issues that need to be assigned. label Oct 30, 2024
@jonathanpeppers
Copy link
Member Author

jonathanpeppers commented Nov 1, 2024

After some conversation, it may be more appropriate for Android to use $(AndroidAotMode)=hybrid anyway. We don't really want people to have to opt into the interpreter, if the JIT can be available.

Some conversation here:

Of course, the drawback to using hybrid is app size!

Summary:
  +           0 Other entries 0.00% (of 2,858,353)
  +           0 Dalvik executables 0.00% (of 15,406,204)
  +  43,171,232 Shared libraries 235.64% (of 18,320,632)
  +  10,569,349 Package size difference 63.65% (of 16,604,909)

Startup time was also either slightly worse (or the same, within margin of error), when using $(AndroidAotMode)=hybrid. It could likely be due to the larger files being loaded at startup. This diminishes the usefulness of the feature.

@jpobst jpobst added the enhancement Proposed change to current functionality. label Nov 1, 2024
@alexyakunin
Copy link

I would rather prefer to have an opportunity to opt into the interpreter on Android - all depends on whether it's faster than JIT specifically on app startup. And if we assume Profiled AOT works (ok, currently it doesn't, but maybe you'll end up fixing this), the % of methods to interpret should be relatively small.

@jonathanpeppers
Copy link
Member Author

I would rather prefer to have an opportunity to opt into the interpreter on Android

@alexyakunin this feels a bit off-topic, but you can do this today in a Release build with:

<PropertyGroup>
  <RunAOTCompilation>false</RunAOTCompilation>
  <UseInterpreter>true</UseInterpreter>
</PropertyGroup>

But I suspect you will see worse performance with this combination. Startup might be OK, but as soon as there is a complicated for-loop, it will perform much slower even than JIT. Additionally, features like hardware intrinsics won't work.

There is no combination of "Normal" AOT mode with interpreter:

We are consumers of the runtime, so we can only use what they provide.

@alexyakunin
Copy link

But I suspect you will see worse performance with this combination.

Yes, it is - we tried this option. As far as I remember, it's worse on Android vs even JIT w/o AOT.

@alexyakunin
Copy link

We are consumers of the runtime, so we can only use what they provide.

@jonathanpeppers What about MONO_AOT_MODE_INTERP and its variants? At glance, it looks like AOT w/o JIT.

@jonathanpeppers
Copy link
Member Author

jonathanpeppers commented Nov 5, 2024

It looks like MONO_AOT_MODE_INTERP is AOT with Interpreter fallback. I discussed in a meeting today, we want to try it out, there are some changes required for it to work.

We'd need to update:

Build time:

public static bool GetAndroidAotMode(string androidAotMode, out AotMode aotMode)
{
aotMode = AotMode.Normal;
switch ((androidAotMode ?? string.Empty).ToLowerInvariant().Trim())
{
case "":
case "none":
aotMode = AotMode.None;
return true;
case "normal":
aotMode = AotMode.Normal;
return true;
case "hybrid":
aotMode = AotMode.Hybrid;
return true;
case "full":
aotMode = AotMode.Full;
return true;
case "interpreter":
// We don't do anything here for this mode, this is just to set the flag for the XA
// runtime to initialize Mono in the interpreter "AOT" mode.
aotMode = AotMode.Interp;
return true;
}
return false;
}

Runtime:

switch (mono_aot_mode_name [0]) {
case 'n':
aotMode = MonoAotMode::MONO_AOT_MODE_NORMAL;
break;
case 'h':
aotMode = MonoAotMode::MONO_AOT_MODE_HYBRID;
break;
case 'f':
aotMode = MonoAotMode::MONO_AOT_MODE_FULL;
break;
case 'i':
aotMode = MonoAotMode::MONO_AOT_MODE_INTERP_ONLY;
break;
default:
aotMode = MonoAotMode::MONO_AOT_MODE_LAST;
break;
}

jonathanpeppers added a commit that referenced this issue Nov 5, 2024
Context: #9469 (comment)

I don't think this actually works, as the AOT compiler fails with:

    > dotnet build -c Release -p:AndroidAotMode=FullInterp -p:AndroidEnableProfiledAot=false -bl -t:Install -r android-x64
    helloandroid failed with 1 error(s) (8.9s)
        D:\src\xamarin-android\bin\Debug\lib\packs\Microsoft.Android.Sdk.Windows\35.99.0\targets\Microsoft.Android.Sdk.Aot.targets(110,5): error :
        Precompiling failed for D:\src\helloandroid\obj\Release\net9.0-android\android-x64\linked\System.Private.CoreLib.dll with exit code -1073740791.
        Mono Ahead of Time compiler - compiling assembly D:\src\helloandroid\obj\Release\net9.0-android\android-x64\linked\System.Private.CoreLib.dll
        AOTID 7FACD039-CD91-2136-1ACD-BC2EDF417C8D
        * Assertion: should not be reached at D:\a\_work\1\s\src\mono\mono\mini\tramp-amd64.c:1216
    helloandroid failed (0.7s) → bin\Release\net9.0-android\android-x64\helloandroid.dll

Which is the assertion here:

https://github.com/dotnet/runtime/blob/7dab903b20269d78c6bc08d5269947db7d35c22b/src/mono/mono/mini/tramp-amd64.c#L1216
@alexyakunin
Copy link

I got an impression iOS uses these modes, + yeah, there is an incompatibility (well, only partial compatibility) between the modes available in Mono runtime & modes you can specify in Android .targets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: App+Library Build Issues when building Library projects or Application projects. Area: App Runtime Issues in `libmonodroid.so`. enhancement Proposed change to current functionality.
Projects
None yet
Development

No branches or pull requests

4 participants