[android] cache `Join` and `Cap` enum values (#24248)
Context: https://github.com/dotnet/maui/issues/23991
Context: https://github.com/chabiss/periodictable
In the above sample, a lot of time is spent in:
921.46ms (4.3%) mono!Android.Graphics.Paint.Cap.get_Butt()
872.40ms (4.1%) mono!Android.Graphics.Paint.Join.get_Miter()
This exposes a performance issue with `Java.Lang.Enum` values:
* `java.lang.Enum` in Java are objects (not `int` like C#)
* When accessing an enum value, Java returns an object we have to wrap
in a C# object.
* .NET for Android has to do bookkeeping around this, lookup in a hash
table, etc.
To avoid this, we can store the `Join` and `Cap` values in a static
field and avoid calling into Java. This approach is already working
in .NET MAUI for `ImageView.ScaleType`:
9361f90a5d/src/Core/src/Platform/Android/AspectExtensions.cs (L7-L10)
After this change, the time spent is completely gone:
2.41ms (0.02%) mono.android!Android.Graphics.Paint.Join.get_Miter()
I can't find the same call for (the unfortunately named) `get_Butt()`
at all.
In the future, we might consider changing the C# binding for
`Java.Lang.Enum` to "auto-cache" values in C# static fields. Not sure
if there is enough time left for it to happen in .NET 9, though.
This commit is contained in:
Родитель
0370361000
Коммит
a02f1d420f
|
@ -15,6 +15,14 @@ namespace Microsoft.Maui.Graphics
|
|||
{
|
||||
public class MauiDrawable : PaintDrawable
|
||||
{
|
||||
static Join? JoinMiter;
|
||||
static Join? JoinBevel;
|
||||
static Join? JoinRound;
|
||||
|
||||
static Cap? CapButt;
|
||||
static Cap? CapSquare;
|
||||
static Cap? CapRound;
|
||||
|
||||
readonly AContext? _context;
|
||||
readonly float _density;
|
||||
|
||||
|
@ -298,20 +306,13 @@ namespace Microsoft.Maui.Graphics
|
|||
|
||||
public void SetBorderLineJoin(LineJoin lineJoin)
|
||||
{
|
||||
Join? aLineJoin = Join.Miter;
|
||||
|
||||
switch (lineJoin)
|
||||
Join? aLineJoin = lineJoin switch
|
||||
{
|
||||
case LineJoin.Miter:
|
||||
aLineJoin = Join.Miter;
|
||||
break;
|
||||
case LineJoin.Bevel:
|
||||
aLineJoin = Join.Bevel;
|
||||
break;
|
||||
case LineJoin.Round:
|
||||
aLineJoin = Join.Round;
|
||||
break;
|
||||
}
|
||||
LineJoin.Miter => JoinMiter ??= Join.Miter,
|
||||
LineJoin.Bevel => JoinBevel ??= Join.Bevel,
|
||||
LineJoin.Round => JoinRound ??= Join.Round,
|
||||
_ => JoinMiter ??= Join.Miter,
|
||||
};
|
||||
|
||||
if (_strokeLineJoin == aLineJoin)
|
||||
return;
|
||||
|
@ -323,20 +324,13 @@ namespace Microsoft.Maui.Graphics
|
|||
|
||||
public void SetBorderLineCap(LineCap lineCap)
|
||||
{
|
||||
Cap? aLineCap = Cap.Butt;
|
||||
|
||||
switch (lineCap)
|
||||
Cap? aLineCap = lineCap switch
|
||||
{
|
||||
case LineCap.Butt:
|
||||
aLineCap = Cap.Butt;
|
||||
break;
|
||||
case LineCap.Square:
|
||||
aLineCap = Cap.Square;
|
||||
break;
|
||||
case LineCap.Round:
|
||||
aLineCap = Cap.Round;
|
||||
break;
|
||||
}
|
||||
LineCap.Butt => CapButt ??= Cap.Butt,
|
||||
LineCap.Square => CapSquare ??= Cap.Square,
|
||||
LineCap.Round => CapRound ??= Cap.Round,
|
||||
_ => CapButt ??= Cap.Butt,
|
||||
};
|
||||
|
||||
if (_strokeLineCap == aLineCap)
|
||||
return;
|
||||
|
|
Загрузка…
Ссылка в новой задаче