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
Description
I'm investigating an app that is very slow in Debug mode:
Note that Debug mode on Android:
$(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:
Using our latest stable releases, you can see this method:
(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:
Mono.Android.dllandJava.Interop.dllthose 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 runReleasemode.Configuration
Other information
Here are some
dotnet-trace's I've recorded of this app: debug_vs_release.zip