-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Skip initial assignments in property mapper (take 4) #27042
base: main
Are you sure you want to change the base?
Skip initial assignments in property mapper (take 4) #27042
Conversation
279a2aa
to
7467d42
Compare
Amazing work @MartyIX . This should be a top priority for the team to review + come up with a feasible solution targeting .net9. One of the major issues that everyone is always talking about is performance. CV, loading pages, etc. This seems very promising to instantly improve performance without changes in a codebase ( again from a user/customer pov) Also : it would be helpful I guess to have a generic method to count the interop calls and see the impact ( not sure if already exists) |
I added a simple comparison to the OP. It shows that by removing setting padding one saved about 180 ms in total when I displayed my grid 10 times. So that property alone seems to shave off 18 ms (more or less) for each display of my grid. This PR is really suboptimal but I think it saves ~50 ms to display each grid. For me
We will see what we can get. Again, this is not finished. To answer your question, I'm not aware of a way to count interop calls precisely but https://www.speedscope.app/ gives good enough estimation of improvements so I'm currently happy with it. |
Interesting one and definitely something for the team to investigate further for its potential. |
ae27366
to
b9d08bc
Compare
b9d08bc
to
84a903d
Compare
@@ -20,6 +22,47 @@ namespace Microsoft.Maui.Handlers | |||
/// Handlers are also responsible for instantiating the underlying platform view, and mapping the cross-platform control API to the platform view API. </remarks> | |||
public abstract partial class ViewHandler : ElementHandler, IViewHandler | |||
{ | |||
#pragma warning disable RS0016 // Add public types and members to the declared API |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Intentionally for now to avoid commiting too many changes.
There are public API changes in this PR!
ae4f780
to
b48688f
Compare
b48688f
to
cbe82e5
Compare
Credits to @albyrock87 for helping me refactor the PR to be acceptable for .NET 9!
Description of Change
This is very much work in progress but it seems to show promising performance implications1.
Introduction to the problem
To understand this PR, it is good to know that each virtual view (e.g., MAUI's
<Entry>
) is mapped to a platform view (e.g.,<TextBox>
on Windows) on each supported platform2.Now when a XAML page with a single
<Entry Text="Hi" />
element is to be to displayed to user by MAUI, MAUI creates a new platform view (i.e.TextBox
on Windows; see doc).In a next step, MAUI must make sure that all properties of
<Entry>
are set (mirrored?) to the newTextBox
instance. So MAUI maps all properties of the virtual view (<Entry>
) to corresponding properties ofTextBox
. So in simple words, what happens when MAUI initializes a platform view is the following (pseudocode):(Code Listing 1)
It's technically more complicated but this is the gist. Now what #17303 observes is that the mapping is not always perfect. One can see it here:
maui/src/Core/src/Handlers/View/ViewHandler.Windows.cs
Lines 42 to 90 in 7a6b1af
So suppose that a new
<Entry>
is to be added to screen by MAUI on Windows, then MAUI calls on a newTextBox
mapping methodsMapTranslationX
,MapTranslationY
,MapScale
, etc. which all do the same work. So it's clear it can be called just once to achieve the same.One might think that it's not a big deal to set, e.g.,
platformView.Projection = null
(like here)3. And that's actually a big deal because each such call is an interop call. Interop calls much more costly than simple .NET calls4. In a sense, it's a death by tousand cuts because as a MAUI app gets more complex, everything takes longer and longer to display. So each removed interop call counts because it expands how big MAUI app one can implement5How to MAUI improve performance?
To improve MAUI performance, one needs to decrease the number of interop calls needed to display a single MAUI window, that is something like:
#virtualViews * #properties ~= virtualViews * 50
Previously tried approaches
WindowsBatchPropertyMapper
to save unnecessary work when initializing views #24417 but it was rejected.isPlatformViewBeingInitialized
and use it in mapper methods to avoid doing work that is not necessary. For example, it's not necessary to setplatformView.Opacity = 1
after the platform view is instantiated because that's its default value.This PR
PlatformMapper
itself and not in platform methods as the previous approach. So we decide "sooner" and this approach is more "centralistic". It IMO follows this comment by @PureWeen.opacity = 1
is default value and if a platform view is instantiated, then when property mapper is called for the first time for that platform view, we don't need to assignopacity = 1
and many others because arguably almost all properties are set to default values and just a few are set to "useful values" (e.g.Entry.Text = "Hi"
but margin = 0, padding = 0, opacity =1, etc. etc.).Performance impact
(Compare
Handler.MapHeight
in both images, etc.)Speedscopes:
Search for
Handler.Map
Issues Fixed
Fixes #17303
Footnotes
As expected. ↩
Read Windows, Mac Catalyst, Android, iOS, etc. ↩
Interestingly, setting some platform view properties (like
RenderTransform
in WinUI) can be much more costly than others. It seems that some parts of WinUI are much less optimized than others. ↩MAUI on Windows is based on WinUI framework and WinRT is used for interop calls (see how costly is accessing Panel.Children here). On Android, one needs to do interop calls as Android apps runs on java virtual machines (JVMs). ↩
I'm not talking about something takes a microsecond, I'm talking about a grid that one can display in 1 second or in 100 ms (see (see https://github.com/dotnet/maui/issues/21787#issuecomment-2453520427 to get some sense what I'm talking about). So this issue is about a real-world issue where even mid-size apps can suffer from poor performance. ↩