Skip to content

Android: Debug Mode & Interpreter Performance #106491

Description

@jonathanpeppers

Description

I'm investigating an app that is very slow in Debug mode:

Note that Debug mode on Android:

  • Uses interpreter for C# hot reload
  • No trimmer, no AOT
  • No XAML compilation, so XAML is parsed
  • $(Optimize) C# compiler setting, etc.

Those are a lot of reasons this is generally, slower.

I think I narrowed down to a basic Java interop method that showcases one slowdown under interp:

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal unsafe static void DeleteLocalRef(nint env, nint instance)
{
    (*(JNIEnv**)env)->DeleteLocalRef(env, instance);
}

// Then the C# function pointer is
internal struct JNIEnv
{
    public unsafe delegate* unmanaged<nint, nint, void> DeleteLocalRef;
}

Using our latest stable releases, you can see this method:

Debug:
1.09s (3.0%) java.interop!Java.Interop.JniEnvironment.References.DeleteLocalRef(intptr)
Release:
274.47ms (1.0%) java.interop!Java.Interop.JniEnvironment.References.DeleteLocalRef(intptr)

(Note that I compared the calling method, because of aggressive inlining)

DeleteLocalRef() is just one instance of a slow method under interp, general Java interop will invoke many other methods like this.

Other ideas:

  • Is there a way we could try to JIT some assemblies and use interp for the rest? If we used JIT for Mono.Android.dll and Java.Interop.dll those would never be C# "hot reloaded".

Reproduction Steps

Debug the sample in VS on Android:

Expected behavior

Performance of (*(JNIEnv**)env)->DeleteLocalRef(env, instance) is reasonable in Debug mode.

Actual behavior

Performance of (*(JNIEnv**)env)->DeleteLocalRef(env, instance) could be improved.

Regression?

No, I think this was always the case.

Known Workarounds

Disable the interpreter with UseInterpreter=false, or run Release mode.

Configuration

dotnet --version
8.0.400

Other information

Here are some dotnet-trace's I've recorded of this app: debug_vs_release.zip

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions