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

[generator] improve *Implementor constructors #1105

Merged
merged 1 commit into from
May 5, 2023

Conversation

jonathanpeppers
Copy link
Member

Context: dotnet/maui#12130
Context: https://github.com/angelru/CvSlowJittering

Profiling a .NET MAUI customer sample while scrolling on a Pixel 5, I see ~2.2% of the time spent in:

(2.2%) mono.android!Android.Views.View.IOnFocusChangeListenerImplementor..ctor()

https://github.com/dotnet/maui/blob/2041476e78452891029f4d2bd806c45be42f4878/src/Core/src/Handlers/View/ViewHandler.Android.cs#L14

MAUI subscribes to Android.Views.View.FocusChange for every view placed on the screen -- which happens while scrolling in this sample.

Reviewing, the generated code for this constructor still uses the outdated JNIEnv APIs:

public IOnFocusChangeListenerImplementor () : base (global::Android.Runtime.JNIEnv.StartCreateInstance ("mono/android/view/View_OnFocusChangeListenerImplementor", "()V"), JniHandleOwnership.TransferLocalRef)
{
    global::Android.Runtime.JNIEnv.FinishCreateInstance (((global::Java.Lang.Object) this).Handle, "()V");
}

Which we can change to use the newer/faster Java.Interop APIs:

public unsafe IOnFocusChangeListenerImplementor () : base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer)
{
    const string __id = "()V";
    if (((global::Java.Lang.Object) this).Handle != IntPtr.Zero)
        return;
    var h = JniPeerMembers.InstanceMethods.StartCreateInstance (__id, ((object) this).GetType (), null);
    SetHandle (h.Handle, JniHandleOwnership.TransferLocalRef);
    JniPeerMembers.InstanceMethods.FinishCreateInstance (__id, this, null);
}

These are better because the equivalent call to JNIEnv.FindClass() is cached among other things.

After these changes, I instead see:

(0.81%) mono.android!Android.Views.View.IOnFocusChangeListenerImplementor..ctor()

This should improve the performance of all C# events that wrap Java listeners -- and all .NET MAUI views on Android.

These changes also stop emitting the [Register] attribute for *Implementor classes:

[global::Android.Runtime.Register ("mono/android/view/View_OnFocusChangeListenerImplementor")]

Which is not needed, because *Implementor classes are generated, internal implementation details.

Context: dotnet/maui#12130
Context: https://github.com/angelru/CvSlowJittering

Profiling a .NET MAUI customer sample while scrolling on a Pixel 5, I
see ~2.2% of the time spent in:

    (2.2%) mono.android!Android.Views.View.IOnFocusChangeListenerImplementor..ctor()

https://github.com/dotnet/maui/blob/2041476e78452891029f4d2bd806c45be42f4878/src/Core/src/Handlers/View/ViewHandler.Android.cs#L14

MAUI subscribes to `Android.Views.View.FocusChange` for every view
placed on the screen -- which happens while scrolling in this sample.

Reviewing, the generated code for this constructor still uses the
outdated `JNIEnv` APIs:

    public IOnFocusChangeListenerImplementor () : base (global::Android.Runtime.JNIEnv.StartCreateInstance ("mono/android/view/View_OnFocusChangeListenerImplementor", "()V"), JniHandleOwnership.TransferLocalRef)
    {
        global::Android.Runtime.JNIEnv.FinishCreateInstance (((global::Java.Lang.Object) this).Handle, "()V");
    }

Which we can change to use the newer/faster Java.Interop APIs:

    public unsafe IOnFocusChangeListenerImplementor () : base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer)
    {
        const string __id = "()V";
        if (((global::Java.Lang.Object) this).Handle != IntPtr.Zero)
            return;
        var h = JniPeerMembers.InstanceMethods.StartCreateInstance (__id, ((object) this).GetType (), null);
        SetHandle (h.Handle, JniHandleOwnership.TransferLocalRef);
        JniPeerMembers.InstanceMethods.FinishCreateInstance (__id, this, null);
    }

These are better because the equivalent call to `JNIEnv.FindClass()`
is cached among other things.

After these changes, I instead see:

    (0.81%) mono.android!Android.Views.View.IOnFocusChangeListenerImplementor..ctor()

This should improve the performance of all C# events that wrap Java
listeners -- and all .NET MAUI views on Android.

These changes also stop emitting the `[Register]` attribute for
`*Implementor` classes:

    [global::Android.Runtime.Register ("mono/android/view/View_OnFocusChangeListenerImplementor")]

Which is not needed, because `*Implementor` classes are generated,
internal implementation details.
jonathanpeppers added a commit to jonathanpeppers/xamarin-android that referenced this pull request May 4, 2023
@jonathanpeppers jonathanpeppers marked this pull request as ready for review May 4, 2023 18:25
@jonathanpeppers jonathanpeppers requested review from jonpryor and jpobst and removed request for jonpryor May 4, 2023 18:25
Copy link
Contributor

@jpobst jpobst left a comment

Choose a reason for hiding this comment

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

I approve that the generator changes look good. I will leave the JNI changes to jonp.

@jonpryor jonpryor merged commit a91ae7f into main May 5, 2023
@jonpryor jonpryor deleted the ImplementorConstructors branch May 5, 2023 19:39
jonpryor pushed a commit to dotnet/android that referenced this pull request May 8, 2023
Changes: dotnet/java-interop@3c2a066...a91ae7f

  * dotnet/java-interop@a91ae7f9: [generator] improve *Implementor constructors (dotnet/java-interop#1105)
  * dotnet/java-interop@7d42864d: [Java.Interop.Tools.Cecil] DirectoryAssemblyResolver+MemoryMappedFile (dotnet/java-interop#1103)

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@github-actions github-actions bot locked and limited conversation to collaborators Apr 12, 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