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

Merge the fixes on SR4 into main #21782

Merged
merged 9 commits into from
Apr 11, 2024
Merged

Merge the fixes on SR4 into main #21782

merged 9 commits into from
Apr 11, 2024

Conversation

mattleibow
Copy link
Member

Description of Change

Upstream all the fixes!

PureWeen and others added 9 commits April 5, 2024 19:38
Context: https://github.com/Redth/MauiCollectionViewGallery
Fixes: #14222

This will conflict with:

* #20352

But I will rework this after it is merged.

Profiling the above sample while scrolling on a Pixel 5, a lot of time
is spent in `FormattedStringExtensions.RecalculateSpanPositions()`:

    (20%) Microsoft.Maui.Controls!Microsoft.Maui.Controls.Platform.FormattedStringExtensions.RecalculateSpanPositions(Android.Widget.TextView,Microsoft.Maui.Controls.Label,Android.Text.SpannableString,Microsoft.Maui.SizeRequest)
    (11%) Microsoft.Maui.Controls!Microsoft.Maui.Controls.Platform.FormattedStringExtensions.FontSpan.UpdateDrawState(Android.Text.TextPaint)
    (11%) Microsoft.Maui.Controls!Microsoft.Maui.Controls.Platform.FormattedStringExtensions.FontSpan.Apply(Android.Text.TextPaint)
    (6.3%) MauiCollectionViewGallery!PoolMathApp.Helpers.FormattedTextExtensions.ToFormattedString(PoolMathApp.Models.FormattedTex

The key contributors are `FontSpan` and `LineHeightSpan` which:

* Implement `MetricAffectingSpan`, an abstract class that allows to
  change the metrics of the text.

* Implement `UpdateDrawState()` and `Apply()` methods that are called
  during draw. Causing frequent Java -> C# interop.

To fix this, let's move the following types from C# to Java:

* `FontSpan` -> `PlatformFontSpan`
* `LetterSpacingSpan` -> `PlatformFontSpan` (use different ctor)
* `LineHeightSpan` -> `PlatformLineHeightSpan`

`PlatformLineHeightSpan` is similar, as it is an implementation of the
`LineHeightSpan` interface.

With these changes, I see a nice improvement while scrolling:

    (5.5%) Microsoft.Maui.Controls!Microsoft.Maui.Controls.Platform.FormattedStringExtensions.RecalculateSpanPositions(Android.Widget.TextView,Microsoft.Maui.Controls.Label,Android.Text.SpannableString,Microsoft.Maui.SizeRequest)
    (4.0%) MauiCollectionViewGallery!PoolMathApp.Helpers.FormattedTextExtensions.ToFormattedString(PoolMathApp.Models.FormattedText

`RecalculateSpanPositions` overall, went from 20% to 5.5%!

Comparing the new types, the times spent calling the constructors are
also improved:

    Before:
    (1.1%) Microsoft.Maui.Controls!Microsoft.Maui.Controls.Platform.FormattedStringExtensions.FontSpan..ctor(Microsoft.Maui.Font,M
    (1.5%) Microsoft.Maui.Controls!Microsoft.Maui.Controls.Platform.FormattedStringExtensions.LetterSpacingSpan..ctor(double)
    After:
    (1.0%) Microsoft.Maui!Microsoft.Maui.PlatformFontSpan..ctor(Android.Content.Context,Android.Graphics.Typeface,bool,single)
    (0.82%) Microsoft.Maui!Microsoft.Maui.PlatformFontSpan..ctor(single)

This should be reasonable for .NET 8servicing, as there should be no
behavior changes and no API changes.

In a future PR, it looks like `FormattedStringExtensions` could be
improved further, but this is a decent starting point that makes it a
lot better.
* Light up HideSoftInputOnTappedChanged for catalyst

* Update HideSoftInputOnTappedPageTests.cs

* - add back

* - switch to reset

* - fix up focus to work for catalyst
* Init the flex item before adding it to the layout

Fixes #21711

In some cases, adding an item before may trigger an update before
the add operation is complete. For example, adding a label with HTML
text may cause the layout to run while the label is being constructed.

To prevent that layout pass from crashing because the flex item is
not yet set, we make sure to first set the flex item, and then add it
to the layout. Then, when the layout pass runs, the item is ready to
be used.

This error might not typically appear in normal XAML layouts because
the items are first set, and then the entire page is inflated. However,
if the layout is part of a CollectionView or items are added
dynamically after the UI is loaded, this layout during add may occur.

* This too

* UI tests

* AutomationId is important :)
Context: #21580
Similar to: #21308

Recording this app in `dotnet-trace`, I saw:

    (0.81%)	Microsoft.MacCatalyst!UIKit.UIView.get_Subviews()

Where this time is spent in:

* `Microsoft.Maui!Microsoft.Maui.Platform.WrapperView`

Reviewing the code, it calls `this.Subviews` twice, which would marshal
and create two arrays. It then calls `Subviews[0]`.

Storing in a local instead will avoid creating the array twice:

    var subviews = Subviews;
    if (subviews.Length == 0)
        return;
    //...
    var child = subviews[0];

This improves things a small amount, but is probably worth it:

    (0.72%)	Microsoft.MacCatalyst!UIKit.UIView.get_Subviews()

I'll think about making an analyzer for this, but  I didn't find any
similar cases that appear in `dotnet-trace` at the moment.

This doesn't fully solve #21580, but it's a small improvement.
@mattleibow mattleibow requested a review from a team as a code owner April 11, 2024 16:46
@mattleibow mattleibow merged commit 0a562dc into main Apr 11, 2024
47 checks passed
@mattleibow mattleibow deleted the dev/sr4-into-main branch April 11, 2024 20:22
@github-actions github-actions bot locked and limited conversation to collaborators May 12, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants