
Skill
maui-performance
optimize .NET MAUI application performance
Description
Fix measurable .NET MAUI performance issues: accurate startup profiling with `maui profile startup` using Release builds and physical devices, janky CollectionView scrolling, compiled bindings, oversized images, and trim/NativeAOT regressions. USE FOR: Debug/emulator profiling mistakes, Release physical-device startup measurements, CollectionView nested ScrollView issues, x:DataType, shallow templates, MauiImage BaseSize, remote/gallery image thumbnails, 4000px decode memory, IL2026, NoWarn traps, source-generated serializers, DynamicDependency, linker descriptors, publish-build validation, and before/after measurement. DO NOT USE FOR: generic UI bugs, workload discovery, or architecture-only work.
SKILL.md
MAUI Performance
Use this skill when the user reports a measurable performance symptom or asks for a performance review. Measure first, then change the smallest thing that can explain the symptom.
Workflow
- Identify the symptom: startup, first page render, scrolling, navigation, memory, image loading, or network-bound delays.
- Inspect target frameworks and configuration. Prefer Release builds for meaningful startup and runtime measurements.
- For startup, use the MAUI CLI profiling surface:
maui profile startup --help
Then run the target app with the appropriate platform/device options. - For UI runtime issues, inspect visual tree depth and logs when DevFlow is available.
- Apply targeted fixes and re-measure.
High-Value Fix Areas
| Symptom | Check |
|---|---|
| Slow startup | Startup profile, excessive work in MauiProgram, synchronous I/O, eager service construction, font/image count |
| Slow bindings | Missing x:DataType, reflection-heavy bindings, converters doing expensive work |
| Janky lists | CollectionView inside ScrollView, complex templates, missing item sizing strategy, image decode size |
| Layout cost | Deep nested layouts, unnecessary Grid nesting, repeated measure invalidations |
| Image memory | Oversized source images, missing MAUI image resizing, unbounded remote image caching |
| Release regression | Debug-only diagnostics leaking into Release, linker/trimming differences |
Image Memory Guidance
A 4000×4000 RGBA PNG decodes to ~64 MB in memory regardless of how small it appears on screen. A 200×200 display-sized image decodes to ~160 KB — 400× less memory. Apply these changes when large images cause scrolling or memory issues:
- Resize images to display size before adding to the project.
- Use the
MauiImagebuild action in.csprojwithBaseSizefor automatic platform-specific resizing:<MauiImage Include="Resources/Images/*.png" BaseSize="400,400" /> - Decode images to display size at runtime when loading from remote URLs.
BaseSizeonly applies to packaged build-time image resources; it does not resize downloaded, camera, gallery, or user-imported images. - Use WebP or SVG for icons and logos that need to scale.
- For list rows, generate or download thumbnails — never decode 4000 × 4000
images inside a
CollectionViewitem template.
- Do not wrap
CollectionViewinScrollView. - Keep item templates shallow and use compiled bindings.
- Prefer fixed or predictable item sizing when possible.
- Load thumbnails sized for display, not full-resolution images.
- Avoid expensive work in property getters used by item templates.
Startup Guardrails
- Avoid network calls and file scans during app construction.
- Register services lazily when possible; do not instantiate heavy services just to register them.
- Defer non-critical initialization until after the first page is visible.
- Keep debug-only logging and DevFlow setup behind
#if DEBUG.
Trimming and NativeAOT Guardrails
- Treat trim and NativeAOT issues as publish-build issues, not Debug-build issues. Reproduce with the same publish properties used by the app.
- Do not silence trim warnings blindly. Warnings such as IL2026 indicate code that may not be safe when members are removed.
- Prefer source-generated serializers and explicit registrations over reflection discovery for app models and services used in trimmed builds.
- When reflection is required, keep the dependency explicit with attributes such
as
DynamicDependencyor a linker descriptor, and document why it is needed. - Test startup and the affected feature after publish; a successful Debug run is not evidence that trimming or NativeAOT is safe.
For System.Text.Json in trimmed or NativeAOT builds, move startup JSON paths to a source-generated context:
[JsonSerializable(typeof(List<Product>))]
internal partial class AppJsonContext : JsonSerializerContext
{
}
var products = JsonSerializer.Deserialize(
json,
AppJsonContext.Default.ListProduct);
Keep the context near app models or serialization infrastructure and add every serialized DTO shape used by the startup path. Do not hide IL2026 with broad warning suppressions when a source-generated serializer can make the dependency explicit.
Validation Checklist
- There is a before/after measurement or a clear reason measurement is blocked.
- Startup investigations use
maui profile startupwhen applicable. - Binding-heavy pages use
x:DataType. - Lists avoid nested scrolling and oversized images.
- Trim/NativeAOT changes are validated with a publish build when applicable.
- Performance fixes do not remove accessibility metadata or automation hooks.
More skills from the maui-labs repository
View all 32 skillsandroid-slim-bindings
create Android slim bindings for .NET
Jul 12.NETAndroidJavaKotlin +1devflow-automation
automate .NET MAUI app state
Jul 12.NETAutomationMAUIMobiledevflow-connect
diagnose DevFlow agent connectivity issues
Jul 12DebuggingMAUINetworkingdotnet-workload-info
discover MAUI workload metadata
Jul 12C#CLIEngineeringMAUIios-slim-bindings
create iOS slim bindings for MAUI
Jul 12.NETiOSMAUISwift +1maui-accessibility
implement accessibility in .NET MAUI apps
Jul 12.NETAccessibilityMAUIMobile +1
More from .NET (Microsoft)
View publishermultithreaded-task-migration
migrate MSBuild tasks to multithreaded mode
msbuild
Jul 22.NETEngineeringPerformanceanalyzing-dotnet-performance
analyze .NET code for performance anti-patterns
skills
Jul 12.NETCode AnalysisDebuggingPerformanceandroid-tombstone-symbolication
symbolicate .NET runtime frames in Android tombstones
skills
Jul 12.NETAndroidDebuggingMicrosoftapple-crash-symbolication
symbolicate .NET runtime frames in crash logs
skills
Jul 12.NETDebuggingiOSmacOS +1assertion-quality
evaluate assertion quality in test suites
skills
Jul 12Code AnalysisQATestingauthor-component
create and review Blazor components
skills
Jul 15.NETBlazorC#UI Components +1