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

[android] improve performance of ActivityExtensions.GetWindowFrame #17256

Merged
merged 2 commits into from
Sep 11, 2023

Conversation

jonathanpeppers
Copy link
Member

I've been working to get back some of our lost startup performance on Android in .NET MAUI. We are really close, a few changes will get .NET 8 on par or faster than .NET 7.

Profiling startup of a dotnet new maui app on a Pixel 5, dotnet-trace reported time spent in:

20.05ms (0.73%)	0.22ns (<0.01%)	microsoft.maui!Microsoft.Maui.Platform.ActivityExtensions.GetWindowFrame(Android.App.Activity)

What is particularly interesting here, is this method is called multiple times on startup:

  • X
  • Y
  • Width
  • Height
  • WindowHandler.ConnectHandler()

In the future, we should come up with a way the PropertyMapper can somehow "collapse" these calls so we can do it once.

For now, however, I took the following C# code that looks to do 3 Java interop calls:

internal static Rect GetWindowFrame(this Android.App.Activity activity)
{
    var wmc = WindowMetricsCalculator.Companion.OrCreate;
    var wm = wmc.ComputeCurrentWindowMetrics(activity);
    var bounds = wm.Bounds;
    return activity.FromPixels(bounds);
}

And moved to Java, so we now have 1:

@NonNull
public static Rect getCurrentWindowMetrics(Activity activity) {
    return WindowMetricsCalculator.Companion
        .getOrCreate()
        .computeCurrentWindowMetrics(activity)
        .getBounds();
}

The result being:

Before:
20.05ms (0.73%)	0.22ns (<0.01%)	microsoft.maui!Microsoft.Maui.Platform.ActivityExtensions.GetWindowFrame(Android.App.Activity)
After:
11.94ms (0.22%)	0.06ns (<0.01%)	microsoft.maui!Microsoft.Maui.Platform.ActivityExtensions.GetWindowFrame(Android.App.Activity)

I'd estimate this might improve startup by ~8ms.

In future .NET releases, we should revisit the PropertyMapper pattern. This could be even better if it was only called once.

I've been working to get back some of our lost startup performance on
Android in .NET MAUI. We are really close, a few changes will get .NET 8
on par or faster than .NET 7.

Profiling startup of a `dotnet new maui` app on a Pixel 5,
`dotnet-trace` reported time spent in:

    20.05ms (0.73%)	0.22ns (<0.01%)	microsoft.maui!Microsoft.Maui.Platform.ActivityExtensions.GetWindowFrame(Android.App.Activity)

What is particularly interesting here, is this method is called multiple
times on startup:

* X
* Y
* Width
* Height
* `WindowHandler.ConnectHandler()`

In the future, we should come up with a way the `PropertyMapper` can
somehow "collapse" these calls so we can do it once.

For now, however, I took the following C# code that looks to do 3 Java
interop calls:

    internal static Rect GetWindowFrame(this Android.App.Activity activity)
    {
        var wmc = WindowMetricsCalculator.Companion.OrCreate;
        var wm = wmc.ComputeCurrentWindowMetrics(activity);
        var bounds = wm.Bounds;
        return activity.FromPixels(bounds);
    }

And moved to Java, so we now have 1:

    @nonnull
    public static Rect getCurrentWindowMetrics(Activity activity) {
        return WindowMetricsCalculator.Companion
            .getOrCreate()
            .computeCurrentWindowMetrics(activity)
            .getBounds();
    }

The result being:

    Before:
    20.05ms (0.73%)	0.22ns (<0.01%)	microsoft.maui!Microsoft.Maui.Platform.ActivityExtensions.GetWindowFrame(Android.App.Activity)
    After:
    11.94ms (0.22%)	0.06ns (<0.01%)	microsoft.maui!Microsoft.Maui.Platform.ActivityExtensions.GetWindowFrame(Android.App.Activity)

I'd estimate this might improve startup by ~8ms.

In future .NET releases, we should revisit the `PropertyMapper` pattern.
This could be *even better* if it was only called once.
@@ -31,5 +31,6 @@ dependencies {
annotationProcessor 'com.github.bumptech.glide:compiler:4.15.1'

implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.window:window:1.1.0'
Copy link
Member Author

Choose a reason for hiding this comment

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

It is OK to add this dependency in Java, because we already have it in C#:

<PackageReference
Update="Xamarin.AndroidX.Window.WindowJava"
Version="1.1.0.1"
/>

We were using the same APIs in C# previously.

@jonathanpeppers jonathanpeppers marked this pull request as ready for review September 7, 2023 21:11
@jonathanpeppers jonathanpeppers requested a review from a team as a code owner September 7, 2023 21:11
@samhouts samhouts added this to the .NET 8 GA milestone Sep 8, 2023
@rmarinho
Copy link
Member

rmarinho commented Sep 8, 2023

Don't we batch these updates? or was this before? only on Xamarin.Forms?

@jonathanpeppers
Copy link
Member Author

jonathanpeppers commented Sep 8, 2023

This is actually the example:

https://github.com/dotnet/maui/blob/main/src/Core/src/Platform/Android/ActivityExtensions.cs

You can see how all these methods would call GetWindowFrame() over and over.

This pattern is all over MAUI, so ideally something to think about in the future.

@rmarinho rmarinho merged commit 2fb0727 into dotnet:main Sep 11, 2023
39 checks passed
@rmarinho
Copy link
Member

This is actually the example:

https://github.com/dotnet/maui/blob/main/src/Core/src/Platform/Android/ActivityExtensions.cs

You can see how all these methods would call GetWindowFrame() over and over.

This pattern is all over MAUI, so ideally something to think about in the future.

Can you please create a issue that we track this as a improvement for net9 ?

@jonathanpeppers jonathanpeppers deleted the GetWindowFrame branch September 11, 2023 13:39
@jonathanpeppers
Copy link
Member Author

The issue is: #17303

@github-actions github-actions bot locked and limited conversation to collaborators Dec 6, 2023
@samhouts samhouts added the fixed-in-8.0.0-rc.2.9373 Look for this fix in 8.0.0-rc.2.9373! label Aug 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
fixed-in-8.0.0-rc.2.9373 Look for this fix in 8.0.0-rc.2.9373! platform/android 🤖
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants