Skip to content

Conversation

@grendello
Copy link
Contributor

@grendello grendello commented Feb 21, 2020

Java.Interop uses the JniAddNativeMethodRegistrationAttribute custom
attribute to determine whether to register native methods for a given
type. It turns out that in most cases there isn't a single instance of
this attribute throughout the application and all the calls to
GetCustomAttribute end up returning nothing while incurring a large
performance penalty on application startup.

Eliminate the call after checking that no type in the application is
decorated with the above custom attribute.

Another observation made while profiling a couple of XA applications was
that the installation of the uncaught exception handler with
Java.Lang.Thread was quite expensive while, in most cases, completely
not useful during startup (and, hopefully, during application lifetime).
Instead of registering a managed type to handle the exceptions, register
the handler in Java which then calls down to Xamarin.Android native
runtime which, in turn, propagates the exception to the managed code.

Gains in startup time are quite nice:

Device name: Pixel 3 XL
Device architecture: arm64-v8a
Number of test runs: 10
Test application: Xamarin.Forms integration test

Native to managed Runtime init Displayed Notes
master 131.278 149.074 789.10 preload enabled; 32-bit build
this commit 49.446 66.989 764.30
master 132.315 147.187 795.60 preload disabled; 32-bit build
this commit 48.876 63.822 754.30
master 121.544 137.736 728.20 preload enabled; 64-bit build
this commit 45.350 61.464 699.50
master 123.448 137.052 727.40 preload disabled; 64-bit build
this commit 44.765 58.047 689.00

Device name: Pixel 3 XL
Device architecture: arm64-v8a
Number of test runs: 10
Test application: Xamarin.Forms "Hello World" app with one label

Native to managed Runtime init Displayed Notes
master 122.090 142.004 639.00 preload enabled; 32-bit build
this commit 44.370 63.803 586.10
master 121.110 134.378 634.20 preload disabled; 32-bit build
this commit 45.085 57.992 580.40
master 120.973 141.235 637.20 preload enabled; 64-bit build
this commit 44.767 63.846 578.50
master 120.785 134.588 627.00 preload disabled; 64-bit build
this commit 44.859 57.590 575.40

@grendello
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Pull request contains merge conflicts.

@grendello grendello changed the title No reflection Startup performance improvements (less reflection) Feb 24, 2020
@radekdoulik radekdoulik self-requested a review February 24, 2020 11:37
Copy link
Member

@radekdoulik radekdoulik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The runtime init improvements are nice! Do you know what might be slowing the Activity Displayed times on 64bit?

@grendello
Copy link
Contributor Author

@radekdoulik I think Activity Displayed is simply not a good way to measure our performance. This figure depends on a number of factors on the Android side - it's the time it takes Android to render the activity surface, make it visible etc etc. It can be affected by a multitude of factors outside of our control. I'm working on a more reliable "entire startup" performance measurement now.

@radekdoulik
Copy link
Member

It was quite reliable for me so far. It would be interesting to compare the Activity Displayed times with video recording to see how much does it correlate to the wall clock.

@grendello
Copy link
Contributor Author

it appears to be heavily influenced by what the device/emulator is doing at the time. From what I saw in a quick test the difference of time between the end of OnResume and Activity Displayed was around 200-250ms (over 10 runs)

@grendello grendello marked this pull request as ready for review February 24, 2020 16:19
@grendello grendello force-pushed the no-reflection branch 3 times, most recently from fd9e623 to d34ac92 Compare February 24, 2020 20:35
internal AndroidRuntime (IntPtr jnienv, IntPtr vm, bool allocNewObjectSupported, IntPtr classLoader, IntPtr classLoader_loadClass)
: base (new AndroidRuntimeOptions (jnienv, vm, allocNewObjectSupported, classLoader, classLoader_loadClass))
internal AndroidRuntime (IntPtr jnienv, IntPtr vm, bool allocNewObjectSupported, IntPtr classLoader, IntPtr classLoader_loadClass,
bool jniAddNativeMethodRegistrationAttributePresent)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, let's not align parameters to (. (I know Emacs likes that. Emacs is wrong. ;-)

Rationale: If (when?) this type is renamed, it means that either all of these will be mis-indented, or they'll need to be re-indented so that things look proper.

Instead, it should be indented two tabstops, and/or all parameters should be done on a newline, each one being two tabstops:

internal AndroidRuntime (IntPtr jnienv,
		IntPtr vm,
		bool allocNewObjectSupported,
		IntPtr classLoader,
		IntPtr classLoader_loadClass,
		bool jniAddNativeMethodRegistrationAttributePresent)
{
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Emacs isn't wrong, but I don't care enough to defend the position :) Changes applied (in 2 more places in addition to this)

GC.SuppressFinalize (obj);
}

internal static void PropagateUncaughtException (IntPtr env, IntPtr javaThreadPtr, IntPtr javaExceptionPtr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would make more sense to just leave this entirely in Java & C...?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should absolutely move all this stuff into XamarinUncaughtExceptionHandler.

Here's my conceptual problem: Thread.getDefaultUncaughtExceptionHandler() forms a "linked list", and it is the responsibility of all Thread.UncaughtExceptionHandler implementations to propagate the exception to their "parent" handler within Thread.UncaughtExceptionHandler.uncaughtException().

The problem here is twofold:

  1. UncaughtExceptionHandler instantiation is "responsible" for calling Thread.DefaultUncaughtExceptionHandler and obtaining the "parent" handler, and
  2. UncaughtExceptionHandler is only instantiated when there's an unhandled exception, so it's not "clean" as of process startup, and
  3. Propagating the unhandled exception is thus poorly defined, plus
  4. It's way confusion trying to keep these four different spots in mind and in sync (XamarinUncaughtExceptionHandler, UncaughtExceptionHandler, JNIEnv.PropagateUncaughtException(), UncaughtExceptionHandler.UncaughtException()).

It does not give me a good feeling.

Instead, let's "move" the "default uncaught exception handler linked list management" of UncaughtExceptionHandler into XamarinUncaughtExceptionHandler, and then move UncaughtExceptionHandler.UncaughtException() into JNIEnv.PropagateUncaughtException().

This should kill two places to try to keep track of things, simplifying logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, changes applied. Working on this I wanted to make the minimum amount of changes to minimize potential of breaking something that's been in place for years, but I agree with your assessment 100%

@radekdoulik
Copy link
Member

I was thinking about the times here and my guess is that because we are postponing the uncaught handler, we are not doing any jni type registration in runtime init anymore. Thus all the JITing of the registration code is delayed between runtime init and activity displayed? That would explain the large gain in runtime init and small difference around activity displayed.

This guess might be confirmed by measuring jit times if needed (https://github.com/xamarin/xamarin-android/blob/master/Documentation/guides/profiling.md#profiling-the-jit-compiler)

@grendello
Copy link
Contributor Author

@radekdoulik yes, less JIT time plays a large role here, another is JNI invocations (much less impact than JIT, though). It is possible that some of the JIT load shifted to the "end" of startup, in this case to the rendering phase.

if (!tmg.Generate (types, TypemapOutputDirectory, GenerateNativeAssembly, out ApplicationConfigTaskState appConfState))
throw new XamarinAndroidException (4308, Properties.Resources.XA4308);
GeneratedBinaryTypeMaps = tmg.GeneratedBinaryTypeMaps.ToArray ();
BuildEngine4.RegisterTaskObject (ApplicationConfigTaskState.RegisterTaskObjectKey, appConfState, RegisteredTaskObjectLifetime.AppDomain, allowEarlyCollection: false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@grendello this is going to put this object in memory until the IDE is closed (and will keep it between projects and builds). Is that your intent?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, no, not really. I thought msbuild goes away after the build is done?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RegisteredTaskObjectLifetime.AppDomain will keep the object in the app domain (the IDE)
RegisteredTaskObjectLifetime.Build will keep it for the duration of the build only. So I guess you want the latter?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RegisteredTaskObjectLifetime.AppDomain will keep the object in the app domain (the IDE)
RegisteredTaskObjectLifetime.Build will keep it for the duration of the build only. So I guess you want the latter?

if (!tmg.Generate (types, TypemapOutputDirectory, GenerateNativeAssembly, out ApplicationConfigTaskState appConfState))
throw new XamarinAndroidException (4308, Properties.Resources.XA4308);
GeneratedBinaryTypeMaps = tmg.GeneratedBinaryTypeMaps.ToArray ();
BuildEngine4.RegisterTaskObject (ApplicationConfigTaskState.RegisterTaskObjectKey, appConfState, RegisteredTaskObjectLifetime.AppDomain, allowEarlyCollection: false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@grendello this is going to put this object in memory until the IDE is closed (and will keep it between projects and builds). Is that your intent?

@grendello grendello added the do-not-merge PR should not be merged. label Feb 25, 2020
@grendello grendello force-pushed the no-reflection branch 6 times, most recently from 6c44310 to b0da9a7 Compare February 27, 2020 10:11
@grendello
Copy link
Contributor Author

Hmm, the tests failed on jenkins again, however locally they worked fine:

~$ adb logcat -c; adb shell am instrument -w Mono.Android_TestsMultiDex/xamarin.android.runtimetests.TestInstrumentation; adb logcat -d > /tmp/log.txt
INSTRUMENTATION_RESULT: failed=0
INSTRUMENTATION_RESULT: inconclusive=0
INSTRUMENTATION_RESULT: nunit2-results-path=/storage/emulated/0/Android/data/Mono.Android_TestsMultiDex/files/Documents/TestResults.xml
INSTRUMENTATION_RESULT: passed=769
INSTRUMENTATION_RESULT: run=771
INSTRUMENTATION_RESULT: skipped=2
INSTRUMENTATION_CODE: -1

jonpryor pushed a commit to dotnet/java-interop that referenced this pull request Mar 6, 2020
Context: dotnet/android#4302
Context: #582

Java.Interop tests use their own runtime which doesn't know about the
results of Xamarin.Android's build process scanning for the presence of
the `[JniAddNativeMethodRegistration]` custom attribute. In addition,
Java.Interop's Java type scanner (for typemaps) does not include in its
results the types in `Java.Interop-Tests` which derive from
`Java.Interop.JavaObject` (which is *functionally* equivalent to
Xamarin.Android's `Java.Lang.Object`) and, thus, the scan doesn't
notice that the custom attribute mentioned above is used by a few test
classes.  In effect, two tests fail with a similar exception:

	Java.Lang.LinkageError : No implementation found for void com.xamarin.interop.CallVirtualFromConstructorDerived.calledFromConstructor(int) (tried Java_com_xamarin_interop_CallVirtualFromConstructorDerived_calledFromConstructor and Java_com_xamarin_interop_CallVirtualFromConstructorDerived_calledFromConstructor__I)
	  at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x0008e] in <d30c11568ddc48d5aff8f2d4b2eaa867>:0
	  at Java.Interop.GenericMarshaler.JniPeerInstanceMethodsExtensions._InvokeConstructor[T] (Java.Interop.JniPeerMembers+JniInstanceMethods peer, System.String constructorSignature, Java.Interop.IJavaPeerable self, T value) [0x00059] in <f6f553d46eb149a29e6542964ef27aaa>:0
	  at Java.Interop.GenericMarshaler.JniPeerInstanceMethodsExtensions.FinishGenericCreateInstance[T] (Java.Interop.JniPeerMembers+JniInstanceMethods peer, System.String constructorSignature, Java.Interop.IJavaPeerable self, T value) [0x00029] in <f6f553d46eb149a29e6542964ef27aaa>:0
	  at Java.InteropTests.CallVirtualFromConstructorBase..ctor (System.Int32 value) [0x0004e] in <d39267c627f54df3bc31406b36effb6c>:0
	  at Java.InteropTests.CallVirtualFromConstructorDerived..ctor (System.Int32 value) [0x00000] in <d39267c627f54df3bc31406b36effb6c>:0
	  at Java.InteropTests.InvokeVirtualFromConstructorTests.InvokeVirtualFromConstructor () [0x00000] in <d39267c627f54df3bc31406b36effb6c>:0
	  at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
	  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0006a] in <26b1d17e27e54492bd3e4105b16bfc7e>:0
	  --- End of managed Java.Lang.LinkageError stack trace ---
	java.lang.UnsatisfiedLinkError: No implementation found for void com.xamarin.interop.CallVirtualFromConstructorDerived.calledFromConstructor(int) (tried Java_com_xamarin_interop_CallVirtualFromConstructorDerived_calledFromConstructor and Java_com_xamarin_interop_CallVirtualFromConstructorDerived_calledFromConstructor__I)
	  at com.xamarin.interop.CallVirtualFromConstructorDerived.calledFromConstructor(Native Method)
	  at com.xamarin.interop.CallVirtualFromConstructorBase.<init>(Unknown Source:35)
	  at com.xamarin.interop.CallVirtualFromConstructorDerived.<init>(Unknown Source:2)
	  at crc64f295cabbf85394f5.TestSuiteInstrumentation.n_onStart(Native Method)
	  at crc64f295cabbf85394f5.TestSuiteInstrumentation.onStart(Unknown Source:0)
	  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189)

Force the tests to always assume the custom attribute is present,
thus restoring the default behavior from before b33d183.
jonpryor added a commit to jonpryor/xamarin-android that referenced this pull request Mar 6, 2020
Changes: dotnet/java-interop@7582716...27cfd45

Context: dotnet#4302

  * dotnet/java-interop@27cfd45: [TestJVM] Force looking for the [JniAddNativeMethodRegistration] (dotnet#595)
jonpryor added a commit that referenced this pull request Mar 6, 2020
Changes: dotnet/java-interop@7582716...27cfd45

Context: #4302

  * dotnet/java-interop@27cfd45: [TestJVM] Force looking for the [JniAddNativeMethodRegistration] (#595)
jonpryor pushed a commit to dotnet/java-interop that referenced this pull request Mar 6, 2020
Context: dotnet/android#4302
Context: #582

Java.Interop tests use their own runtime which doesn't know about the
results of Xamarin.Android's build process scanning for the presence of
the `[JniAddNativeMethodRegistration]` custom attribute. In addition,
Java.Interop's Java type scanner (for typemaps) does not include in its
results the types in `Java.Interop-Tests` which derive from
`Java.Interop.JavaObject` (which is *functionally* equivalent to
Xamarin.Android's `Java.Lang.Object`) and, thus, the scan doesn't
notice that the custom attribute mentioned above is used by a few test
classes.  In effect, two tests fail with a similar exception:

	Java.Lang.LinkageError : No implementation found for void com.xamarin.interop.CallVirtualFromConstructorDerived.calledFromConstructor(int) (tried Java_com_xamarin_interop_CallVirtualFromConstructorDerived_calledFromConstructor and Java_com_xamarin_interop_CallVirtualFromConstructorDerived_calledFromConstructor__I)
	  at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x0008e] in <d30c11568ddc48d5aff8f2d4b2eaa867>:0
	  at Java.Interop.GenericMarshaler.JniPeerInstanceMethodsExtensions._InvokeConstructor[T] (Java.Interop.JniPeerMembers+JniInstanceMethods peer, System.String constructorSignature, Java.Interop.IJavaPeerable self, T value) [0x00059] in <f6f553d46eb149a29e6542964ef27aaa>:0
	  at Java.Interop.GenericMarshaler.JniPeerInstanceMethodsExtensions.FinishGenericCreateInstance[T] (Java.Interop.JniPeerMembers+JniInstanceMethods peer, System.String constructorSignature, Java.Interop.IJavaPeerable self, T value) [0x00029] in <f6f553d46eb149a29e6542964ef27aaa>:0
	  at Java.InteropTests.CallVirtualFromConstructorBase..ctor (System.Int32 value) [0x0004e] in <d39267c627f54df3bc31406b36effb6c>:0
	  at Java.InteropTests.CallVirtualFromConstructorDerived..ctor (System.Int32 value) [0x00000] in <d39267c627f54df3bc31406b36effb6c>:0
	  at Java.InteropTests.InvokeVirtualFromConstructorTests.InvokeVirtualFromConstructor () [0x00000] in <d39267c627f54df3bc31406b36effb6c>:0
	  at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
	  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0006a] in <26b1d17e27e54492bd3e4105b16bfc7e>:0
	  --- End of managed Java.Lang.LinkageError stack trace ---
	java.lang.UnsatisfiedLinkError: No implementation found for void com.xamarin.interop.CallVirtualFromConstructorDerived.calledFromConstructor(int) (tried Java_com_xamarin_interop_CallVirtualFromConstructorDerived_calledFromConstructor and Java_com_xamarin_interop_CallVirtualFromConstructorDerived_calledFromConstructor__I)
	  at com.xamarin.interop.CallVirtualFromConstructorDerived.calledFromConstructor(Native Method)
	  at com.xamarin.interop.CallVirtualFromConstructorBase.<init>(Unknown Source:35)
	  at com.xamarin.interop.CallVirtualFromConstructorDerived.<init>(Unknown Source:2)
	  at crc64f295cabbf85394f5.TestSuiteInstrumentation.n_onStart(Native Method)
	  at crc64f295cabbf85394f5.TestSuiteInstrumentation.onStart(Unknown Source:0)
	  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189)

Force the tests to always assume the custom attribute is present,
thus restoring the default behavior from before b33d183.
jonpryor added a commit that referenced this pull request Mar 6, 2020
Changes: dotnet/java-interop@9324e1e...35f30bf

Context: #4302

  * dotnet/java-interop@35f30bf4: [TestJVM] Force looking for the [JniAddNativeMethodRegistration] (#595)
@grendello grendello force-pushed the no-reflection branch 3 times, most recently from c82f7d7 to 4b8a050 Compare March 6, 2020 21:13
@grendello
Copy link
Contributor Author

There's a linker failure in a couple of tests:

/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000: Mono.Linker.MarkException: Error processing method: 'System.Void Android.Runtime.JNIEnv::PropagateUncaughtException(System.IntPtr,System.IntPtr,System.IntPtr)' in assembly: 'Mono.Android.dll' ---> Mono.Cecil.ResolutionException: Failed to resolve System.Void System.Diagnostics.Debugger::Mono_UnhandledException(System.Exception) [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Mono.Linker.Steps.MarkStep.HandleUnresolvedMethod (Mono.Cecil.MethodReference reference) [0x00013] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Mono.Linker.Steps.MarkStep.MarkMethod (Mono.Cecil.MethodReference reference) [0x00049] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Mono.Linker.Steps.MarkStep.MarkInstruction (Mono.Cecil.Cil.Instruction instruction) [0x00040] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Mono.Linker.Steps.MarkStep.MarkMethodBody (Mono.Cecil.Cil.MethodBody body) [0x000c2] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Mono.Linker.Steps.MarkStep.ProcessMethod (Mono.Cecil.MethodDefinition method) [0x001b1] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Mono.Linker.Steps.MarkStep.ProcessQueue () [0x0001b] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:    --- End of inner exception stack trace --- [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Mono.Linker.Steps.MarkStep.ProcessQueue () [0x00047] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Mono.Linker.Steps.MarkStep.ProcessPrimaryQueue () [0x0000a] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Mono.Linker.Steps.MarkStep.Process () [0x00102] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Mono.Linker.Steps.MarkStep.Process (Mono.Linker.LinkContext context) [0x0000d] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at MonoDroid.Tuner.MonoDroidMarkStep.Process (Mono.Linker.LinkContext context) [0x0000b] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Mono.Linker.Pipeline.ProcessStep (Mono.Linker.LinkContext context, Mono.Linker.Steps.IStep step) [0x0000d] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Mono.Linker.Pipeline.Process (Mono.Linker.LinkContext context) [0x0000f] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at MonoDroid.Tuner.Linker.Run (Mono.Linker.Pipeline pipeline, Mono.Linker.LinkContext context) [0x00000] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at MonoDroid.Tuner.Linker.Process (MonoDroid.Tuner.LinkerOptions options, Mono.Linker.ILogger logger, Mono.Linker.LinkContext& context) [0x00071] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Xamarin.Android.Tasks.LinkAssemblies.Execute (Java.Interop.Tools.Cecil.DirectoryAssemblyResolver res) [0x001dd] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Xamarin.Android.Tasks.LinkAssemblies.RunTask () [0x0001b] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(1952,5): error XALNK7000:   at Xamarin.Android.Tasks.AndroidTask.Execute () [0x00000] in <6058e84c219b4da3a4d18108456c91f7>:0  [/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/UnnamedProject.csproj]
Done executing task "LinkAssemblies" -- FAILED. (TaskId:125)

However, this is caused by the wrong mscorlib being passed to the LinkAssemblies task:

Task "LinkAssemblies" (TaskId:125)
  Task Parameter:UseSharedRuntime=False (TaskId:125)
  Task Parameter:MainAssembly=/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/bin/Release/UnnamedProject.dll (TaskId:125)
  Task Parameter:OutputDirectory=obj/Release/android/assets/ (TaskId:125)
  Task Parameter:LinkMode=SdkOnly (TaskId:125)
  Task Parameter:PreserveJniMarshalMethods=False (TaskId:125)
  Task Parameter:
      ResolvedAssemblies=
          /Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/bin/Release/UnnamedProject.dll
                  HasMonoAndroidReference=True
                  OriginalItemSpec=bin/Release/UnnamedProject.dll
                  ReferenceAssembly=/Users/runner/runners/2.165.1/work/1/s/bin/TestRelease/temp/Bug12935_True/bin/Release/UnnamedProject.dll
                  TargetFrameworkIdentifier=MonoAndroid
          /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/Java.Interop.dll
                  CopyLocal=false
                  FrameworkFile=true
                  FusionName=Java.Interop, Version=0.1.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065
                  OriginalItemSpec=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/Java.Interop.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/Java.Interop.dll
                  ReferenceSourceTarget=ResolveAssemblyReference
                  ResolvedFrom={TargetFrameworkDirectory}
                  TargetFrameworkIdentifier=MonoAndroid
                  Version=
          /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v10.0/Mono.Android.dll
                  CopyLocal=false
                  FrameworkFile=true
                  FusionName=Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065
                  OriginalItemSpec=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v10.0/Mono.Android.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v10.0/Mono.Android.dll
                  ReferenceSourceTarget=ResolveAssemblyReference
                  ResolvedFrom={TargetFrameworkDirectory}
                  TargetFrameworkIdentifier=MonoAndroid
                  Version=
          /Library/Frameworks/Mono.framework/Versions/6.10.0/lib/mono/4.5/mscorlib.dll
                  CopyLocal=true
                  FusionName=mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
                  OriginalItemSpec=/Library/Frameworks/Mono.framework/Versions/6.10.0/lib/mono/4.5/mscorlib.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/Versions/6.10.0/lib/mono/4.5/mscorlib.dll
                  ReferenceSourceTarget=ResolveAssemblyReference
                  ResolvedFrom=/Library/Frameworks/Mono.framework/Versions/6.10.0/lib/mono/4.5/mscorlib.dll
                  Version=
          /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.Core.dll
                  CopyLocal=false
                  FrameworkFile=true
                  FusionName=System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
                  OriginalItemSpec=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.Core.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.Core.dll
                  ReferenceSourceTarget=ResolveAssemblyReference
                  ResolvedFrom={TargetFrameworkDirectory}
                  Version=
          /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.dll
                  CopyLocal=false
                  FrameworkFile=true
                  FusionName=System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
                  OriginalItemSpec=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.dll
                  ReferenceSourceTarget=ResolveAssemblyReference
                  ResolvedFrom={TargetFrameworkDirectory}
                  Version=
          /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/Facades/System.Runtime.dll
                  CopyLocal=false
                  FrameworkFile=true
                  FusionName=System.Runtime, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
                  OriginalItemSpec=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/Facades/System.Runtime.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/Facades/System.Runtime.dll
                  ReferenceSourceTarget=ResolveAssemblyReference
                  ResolvedFrom={TargetFrameworkDirectory}
                  Version=
          /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.Xml.dll
                  CopyLocal=false
                  FrameworkFile=true
                  FusionName=System.Xml, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
                  OriginalItemSpec=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.Xml.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.Xml.dll
                  ReferenceSourceTarget=ResolveAssemblyReference
                  ResolvedFrom={TargetFrameworkDirectory}
                  Version=
          /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.Net.Http.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.Net.Http.dll
          /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/Facades/System.Drawing.Common.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/Facades/System.Drawing.Common.dll
          /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.Runtime.Serialization.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.Runtime.Serialization.dll
          /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.ServiceModel.Internals.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.ServiceModel.Internals.dll
          /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/Mono.Security.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/Mono.Security.dll
          /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.Numerics.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.Numerics.dll
          /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.ComponentModel.Composition.dll
                  ReferenceAssembly=/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.ComponentModel.Composition.dll (TaskId:125)

I am unable to reproduce the error locally (tried both with XA master and this PR). @dellis1972, @jonathanpeppers any clue as to what might be going on?

@dellis1972
Copy link
Contributor

So it looks like we are hitting this following code https://github.com/microsoft/msbuild/blame/e5218a90cf743c8bd5f489c36e72643d8a8c6c61/src/Tasks/Microsoft.CSharp.CurrentVersion.targets#L372. Which is auto including mscorlib from the system .net.

Interestingly NoCompilerStandardLib is true in the build log, but NoStdLib is NOT in the log at all which is why we are hitting this code. However we only set NoStdLib in the VB.targets and it is empty by default for C# .

@jonpryor
Copy link
Contributor

jonpryor commented Mar 9, 2020

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Java.Interop uses the `JniAddNativeMethodRegistrationAttribute` custom
attribute to determine whether to register native methods for a given
type. It turns out that in most cases there isn't a single instance of
this attribute throughout the application and all the calls to
`GetCustomAttribute` end up returning nothing while incurring a large
performance penalty on application startup.

Eliminate the call after checking that no type in the application is
decorated with the above custom attribute.

Another observation made while profiling a couple of XA applications was
that the installation of the uncaught exception handler with
`Java.Lang.Thread` was quite expensive while, in most cases, completely
not useful during startup (and, hopefully, during application lifetime).
Instead of registering a managed type to handle the exceptions, register
the handler in Java which then calls down to Xamarin.Android native
runtime which, in turn, propagates the exception to the managed code.

Gains in startup time are quite nice:

Device name: **Pixel 3 XL**
Device architecture: **arm64-v8a**
Number of test runs: **10**
Test application: **Xamarin.Forms integration test**

|                 | **Native to managed**  | **Runtime init** | **Displayed** | **Notes**                      |
|-----------------|------------------------|------------------|---------------|--------------------------------|
| **master**      | 131.278                | 149.074          | 789.10        |  preload enabled; 32-bit build |
| **this commit** | 49.446                 | 66.989           | 764.30        |                                |
| **master**      | 132.315                | 147.187          | 795.60        | preload disabled; 32-bit build |
| **this commit** | 48.876                 | 63.822           | 754.30        |                                |
| **master**      | 121.544                | 137.736          | 728.20        |  preload enabled; 64-bit build |
| **this commit** | 45.350                 | 61.464           | 699.50        |                                |
| **master**      | 123.448                | 137.052          | 727.40        | preload disabled; 64-bit build |
| **this commit** | 44.765                 | 58.047           | 689.00        |                                |

Device name: **Pixel 3 XL**
Device architecture: **arm64-v8a**
Number of test runs: **10**
Test application: Xamarin.Forms "Hello World" app with one label

|                 | **Native to managed**  | **Runtime init** | **Displayed** | **Notes**                      |
|-----------------|------------------------|------------------|---------------|--------------------------------|
| **master**      | 122.090                | 142.004          | 639.00        |  preload enabled; 32-bit build |
| **this commit** | 44.370                 | 63.803           | 586.10        |                                |
| **master**      | 121.110                | 134.378          | 634.20        | preload disabled; 32-bit build |
| **this commit** | 45.085                 | 57.992           | 580.40        |                                |
| **master**      | 120.973                | 141.235          | 637.20        |  preload enabled; 64-bit build |
| **this commit** | 44.767                 | 63.846           | 578.50        |                                |
| **master**      | 120.785                | 134.588          | 627.00        | preload disabled; 64-bit build |
| **this commit** | 44.859                 | 57.590           | 575.40        |                                |
@jonpryor jonpryor merged commit 2aff4e7 into dotnet:master Mar 10, 2020
@grendello grendello deleted the no-reflection branch March 10, 2020 14:20
pjcollins pushed a commit to dotnet/java-interop that referenced this pull request Mar 10, 2020
Context: dotnet/android#4302
Context: #582

Java.Interop tests use their own runtime which doesn't know about the
results of Xamarin.Android's build process scanning for the presence of
the `[JniAddNativeMethodRegistration]` custom attribute. In addition,
Java.Interop's Java type scanner (for typemaps) does not include in its
results the types in `Java.Interop-Tests` which derive from
`Java.Interop.JavaObject` (which is *functionally* equivalent to
Xamarin.Android's `Java.Lang.Object`) and, thus, the scan doesn't
notice that the custom attribute mentioned above is used by a few test
classes.  In effect, two tests fail with a similar exception:

	Java.Lang.LinkageError : No implementation found for void com.xamarin.interop.CallVirtualFromConstructorDerived.calledFromConstructor(int) (tried Java_com_xamarin_interop_CallVirtualFromConstructorDerived_calledFromConstructor and Java_com_xamarin_interop_CallVirtualFromConstructorDerived_calledFromConstructor__I)
	  at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x0008e] in <d30c11568ddc48d5aff8f2d4b2eaa867>:0
	  at Java.Interop.GenericMarshaler.JniPeerInstanceMethodsExtensions._InvokeConstructor[T] (Java.Interop.JniPeerMembers+JniInstanceMethods peer, System.String constructorSignature, Java.Interop.IJavaPeerable self, T value) [0x00059] in <f6f553d46eb149a29e6542964ef27aaa>:0
	  at Java.Interop.GenericMarshaler.JniPeerInstanceMethodsExtensions.FinishGenericCreateInstance[T] (Java.Interop.JniPeerMembers+JniInstanceMethods peer, System.String constructorSignature, Java.Interop.IJavaPeerable self, T value) [0x00029] in <f6f553d46eb149a29e6542964ef27aaa>:0
	  at Java.InteropTests.CallVirtualFromConstructorBase..ctor (System.Int32 value) [0x0004e] in <d39267c627f54df3bc31406b36effb6c>:0
	  at Java.InteropTests.CallVirtualFromConstructorDerived..ctor (System.Int32 value) [0x00000] in <d39267c627f54df3bc31406b36effb6c>:0
	  at Java.InteropTests.InvokeVirtualFromConstructorTests.InvokeVirtualFromConstructor () [0x00000] in <d39267c627f54df3bc31406b36effb6c>:0
	  at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
	  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0006a] in <26b1d17e27e54492bd3e4105b16bfc7e>:0
	  --- End of managed Java.Lang.LinkageError stack trace ---
	java.lang.UnsatisfiedLinkError: No implementation found for void com.xamarin.interop.CallVirtualFromConstructorDerived.calledFromConstructor(int) (tried Java_com_xamarin_interop_CallVirtualFromConstructorDerived_calledFromConstructor and Java_com_xamarin_interop_CallVirtualFromConstructorDerived_calledFromConstructor__I)
	  at com.xamarin.interop.CallVirtualFromConstructorDerived.calledFromConstructor(Native Method)
	  at com.xamarin.interop.CallVirtualFromConstructorBase.<init>(Unknown Source:35)
	  at com.xamarin.interop.CallVirtualFromConstructorDerived.<init>(Unknown Source:2)
	  at crc64f295cabbf85394f5.TestSuiteInstrumentation.n_onStart(Native Method)
	  at crc64f295cabbf85394f5.TestSuiteInstrumentation.onStart(Unknown Source:0)
	  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189)

Force the tests to always assume the custom attribute is present,
thus restoring the default behavior from before b33d183.
jonpryor pushed a commit that referenced this pull request Mar 10, 2020
Reduce or remove reflection use around JNI method registration, and
rework how uncaught exceptions are handled.

Java.Interop provides an alternate mechanism to allow registering
Java native methods:
[the `[JniAddNativeMethodRegistrationAttribute]` custom attribute][0]
which can be placed on methods of a type to allow "manual"
insertion into the [`JNIEnv::RegisterNatives()`][2] process.

The `Java.Interop-Tests.dll` unit test assembly (130905e) uses this
alternate native method registration mechanism..

Unfortunately, `[JniAddNativeMethodRegistration]` is looked up via
Reflection, which isn't exactly "fast".

Given that `[JniAddNativeMethodRegistration]` is only used by one
assembly *in the world*, let's optimize the common case:
[dotnet/java-interop@b33d183d][3] made the
`[JniAddNativeMethodRegistration]` lookup *optional*.  Disable the
custom attribute lookup *by default*, and allow it to be enabled by
setting the `$(_SkipJniAddNativeMethodRegistrationAttributeScan)`
MSBuild property to True.  Yes, this property is "private".  We'll
investigate more automatic and optimized ideas in the future.

Rework how Java-side unhandled exceptions are processed.  Previously,
this was handled by the `Android.Runtime.UncaughtExceptionHandler`
class, which was constructed during process startup.  A side effect
of this is that it required going through the (*normal* reflection-
based) JNI registration logic of `mono.android.Runtime.register()`,
contributing to startup for something that *ideally* would
Never Happen™.  (Nobody likes unhandled exceptions.)

Changes this so that instead of a C#-side `UncaughtExceptionHandler`
type we instead have a Java-side
`mono.android.XamarinUncaughtExceptionHandler` type which is
created and provided to
`java.lang.Thread.setDefaultUncaughtExceptionHandler()` during
startup.  `XamarinUncaughtExceptionHandler` doesn't do anything until
Java calls `XamarinUncaughtExceptionHandler.uncaughtException()`,
which in turn invokes `Runtime.propagateUncaughtException()`, which
in turn does what `UncaughtExceptionHandler` previously did: lookup
`AppDomain.DoUnhandledException()` via Reflection and invoke it, thus
raising the `AppDomain.UnhandledException` event.

In this manner all overheads associated with unhandled exceptions are
delayed until the exception happens, with minimal impact on startup.

Gains in startup time are quite nice:

  * Device name: **Pixel 3 XL**
  * Device architecture: **arm64-v8a**
  * Number of test runs: **10**
  * Test application: **Xamarin.Forms integration test**

|                 | **Native to managed**  | **Runtime init** | **Displayed** | **Notes**                      |
|-----------------|------------------------|------------------|---------------|--------------------------------|
| **master**      | 131.278                | 149.074          | 789.10        |  preload enabled; 32-bit build |
| **this commit** | 49.446                 | 66.989           | 764.30        |                                |
| **master**      | 132.315                | 147.187          | 795.60        | preload disabled; 32-bit build |
| **this commit** | 48.876                 | 63.822           | 754.30        |                                |
| **master**      | 121.544                | 137.736          | 728.20        |  preload enabled; 64-bit build |
| **this commit** | 45.350                 | 61.464           | 699.50        |                                |
| **master**      | 123.448                | 137.052          | 727.40        | preload disabled; 64-bit build |
| **this commit** | 44.765                 | 58.047           | 689.00        |                                |

  * Device name: **Pixel 3 XL**
  * Device architecture: **arm64-v8a**
  * Number of test runs: **10**
  * Test application: Xamarin.Forms "Hello World" app with one label

|                 | **Native to managed**  | **Runtime init** | **Displayed** | **Notes**                      |
|-----------------|------------------------|------------------|---------------|--------------------------------|
| **master**      | 122.090                | 142.004          | 639.00        |  preload enabled; 32-bit build |
| **this commit** | 44.370                 | 63.803           | 586.10        |                                |
| **master**      | 121.110                | 134.378          | 634.20        | preload disabled; 32-bit build |
| **this commit** | 45.085                 | 57.992           | 580.40        |                                |
| **master**      | 120.973                | 141.235          | 637.20        |  preload enabled; 64-bit build |
| **this commit** | 44.767                 | 63.846           | 578.50        |                                |
| **master**      | 120.785                | 134.588          | 627.00        | preload disabled; 64-bit build |
| **this commit** | 44.859                 | 57.590           | 575.40        |                                |

[0]: dotnet/java-interop@7d51163
[2]: https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#RegisterNatives
[3]: dotnet/java-interop@b33d183
@github-actions github-actions bot locked and limited conversation to collaborators Jan 28, 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.

6 participants