-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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] reduce interop calls in MauiDrawable #14933
[android] reduce interop calls in MauiDrawable #14933
Conversation
Context: dotnet#12130 Context: https://github.com/angelru/CvSlowJittering Profiling a .NET MAUI customer sample while scrolling on a Pixel 5, I see some interesting time being spent in: (0.76%) microsoft.maui!Microsoft.Maui.Graphics.MauiDrawable.OnDraw(Android.Graphics.Drawables.Shapes.Shape,Android.Graphics.Canv (0.54%) microsoft.maui!Microsoft.Maui.Graphics.MauiDrawable.SetDefaultBackgroundColor() This sample has a `<Border/>` inside a `<CollectionView/>` and so you can see this work happening while scrolling. Specifically, I found a couple places we had code like: _borderPaint.StrokeWidth = _strokeThickness; _borderPaint.StrokeJoin = _strokeLineJoin; _borderPaint.StrokeCap = _strokeLineCap; _borderPaint.StrokeMiter = _strokeMiterLimit * 2; if (_borderPathEffect != null) _borderPaint.SetPathEffect(_borderPathEffect); This calls from C# to Java 5 times. Creating a new method in `PlatformInterop.java` allowed me to reduce it to 1. I also found: void SetDefaultBackgroundColor() { using (var background = new TypedValue()) { if (_context == null || _context.Theme == null || _context.Resources == null) return; if (_context.Theme.ResolveAttribute(global::Android.Resource.Attribute.WindowBackground, background, true)) { var resource = _context.Resources.GetResourceTypeName(background.ResourceId); var type = resource?.ToLowerInvariant(); if (type == "color") { var color = new AColor(ContextCompat.GetColor(_context, background.ResourceId)); _backgroundColor = color; } } } } This is doing a lot of unnecessary stuff: looking up a resource by name, etc. I found a very simple Java example we could put in `PlatformInterop.java`: https://stackoverflow.com/a/14468034 After these changes, I now see: (0.28%) microsoft.maui!Microsoft.Maui.Graphics.MauiDrawable.OnDraw(Android.Graphics.Drawables.Shapes.Shape,Android.Graphics.Canv (0.04%) microsoft.maui!Microsoft.Maui.Graphics.MauiDrawable.SetDefaultBackgroundColor() This improves the performance of any `<Border/>` (and other shapes) on Android, and drops about ~1% of the CPU time while scrolling in this example.
if (canvas == null) | ||
if (canvas == null || _clipPath == null) | ||
return; | ||
|
||
var saveCount = canvas.SaveLayer(0, 0, _width, _height, null); | ||
|
||
if (_clipPath != null && Paint != null) | ||
canvas.DrawPath(_clipPath, Paint); | ||
|
||
if (_clipPath != null && _borderPaint != null) | ||
canvas.DrawPath(_clipPath, _borderPaint); | ||
|
||
canvas.RestoreToCount(saveCount); | ||
PlatformInterop.DrawMauiDrawablePath(this, canvas, _width, _height, _clipPath, _borderPaint); |
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.
If _clipPath
is null we can return early here, no need to call canvas.SaveLayer/RestoreToCount
.
@jsuarezruiz @PureWeen is there a sample I can test that it looks exactly the same? Something with a Border & interesting clipping/shapes, etc.? |
Launching the .NET MAUI Gallery can use the Control > border samples. Or, for example https://github.com/jsuarezruiz/netmaui-surfing-app-challenge |
Context: #12130 Context: https://github.com/angelru/CvSlowJittering Profiling a .NET MAUI customer sample while scrolling on a Pixel 5, I see some interesting time being spent in: (0.76%) microsoft.maui!Microsoft.Maui.Graphics.MauiDrawable.OnDraw(Android.Graphics.Drawables.Shapes.Shape,Android.Graphics.Canv (0.54%) microsoft.maui!Microsoft.Maui.Graphics.MauiDrawable.SetDefaultBackgroundColor() This sample has a `<Border/>` inside a `<CollectionView/>` and so you can see this work happening while scrolling. Specifically, I found a couple places we had code like: _borderPaint.StrokeWidth = _strokeThickness; _borderPaint.StrokeJoin = _strokeLineJoin; _borderPaint.StrokeCap = _strokeLineCap; _borderPaint.StrokeMiter = _strokeMiterLimit * 2; if (_borderPathEffect != null) _borderPaint.SetPathEffect(_borderPathEffect); This calls from C# to Java 5 times. Creating a new method in `PlatformInterop.java` allowed me to reduce it to 1. I also found: void SetDefaultBackgroundColor() { using (var background = new TypedValue()) { if (_context == null || _context.Theme == null || _context.Resources == null) return; if (_context.Theme.ResolveAttribute(global::Android.Resource.Attribute.WindowBackground, background, true)) { var resource = _context.Resources.GetResourceTypeName(background.ResourceId); var type = resource?.ToLowerInvariant(); if (type == "color") { var color = new AColor(ContextCompat.GetColor(_context, background.ResourceId)); _backgroundColor = color; } } } } This is doing a lot of unnecessary stuff: looking up a resource by name, etc. I found a very simple Java example we could put in `PlatformInterop.java`: https://stackoverflow.com/a/14468034 After these changes, I now see: (0.28%) microsoft.maui!Microsoft.Maui.Graphics.MauiDrawable.OnDraw(Android.Graphics.Drawables.Shapes.Shape,Android.Graphics.Canv (0.04%) microsoft.maui!Microsoft.Maui.Graphics.MauiDrawable.SetDefaultBackgroundColor() This improves the performance of any `<Border/>` (and other shapes) on Android, and drops about ~1% of the CPU time while scrolling in this example.
Context: #12130
Context: https://github.com/angelru/CvSlowJittering
Profiling a .NET MAUI customer sample while scrolling on a Pixel 5, I see some interesting time being spent in:
This sample has a
<Border/>
inside a<CollectionView/>
and so you can see this work happening while scrolling.Specifically, I found a couple places we had code like:
This calls from C# to Java 5 times. Creating a new method in
PlatformInterop.java
allowed me to reduce it to 1.I also found:
This is doing a lot of unnecessary stuff: looking up a resource by name, etc. I found a very simple Java example we could put in
PlatformInterop.java
:https://stackoverflow.com/a/14468034
After these changes, I now see:
This improves the performance of any
<Border/>
(and other shapes) on Android, and drops about ~1% of the CPU time while scrolling in this example.