- .NET MAUI Performance Optimization
- Profiling
- dotnet-trace
-
- Cross-platform profiler for all MAUI targets. Collect traces with:
- dotnet-trace collect --process-id
- <
- PID
- >
- --providers
- Microsoft-DotNETCore-SampleProfiler
- PerfView
- (Windows only): Use for deep allocation and CPU analysis on WinUI targets.
- Profile before optimizing — measure, don't guess.
- Compiled Bindings
- Always set
- x:DataType
- on pages/views to enable compiled bindings.
- Compiled bindings are
- 8–20× faster
- than reflection-based bindings.
- Required
- for NativeAOT and full trimming — reflection bindings break under trimming.
- Apply
- x:DataType
- at the highest reasonable scope (page or root element).
- <
- ContentPage
- xmlns:
- vm
- =
- "
- clr-namespace:MyApp.ViewModels
- "
- x:
- DataType
- =
- "
- vm:MainViewModel
- "
- >
- <
- Label
- Text
- =
- "
- {Binding Title}
- "
- />
- </
- ContentPage
- >
- For
- DataTemplate
- inside
- CollectionView
- /
- ListView
- , set
- x:DataType
- on the template root:
- <
- DataTemplate
- x:
- DataType
- =
- "
- model:Item
- "
- >
- <
- Label
- Text
- =
- "
- {Binding Name}
- "
- />
- </
- DataTemplate
- >
- Minimize unnecessary bindings
-
- Static content that never changes doesn't need
- {Binding}
- . Use literal values or
- x:Static
- instead.
- Layout Optimization
- Avoid nested single-child layouts
- — a
- StackLayout
- with one child is pointless overhead.
- Prefer
- Grid
- over nested
- StackLayout
- /
- VerticalStackLayout
- — Grid resolves layout in a single pass.
- Use
- IsVisible="False"
- to hide elements rather than adding/removing from the tree at runtime.
- Remove unnecessary wrapper containers — every layout adds a measure/arrange pass.
- Avoid
- AbsoluteLayout
- when
- Grid
- with row/column definitions achieves the same result.
- Set explicit
- WidthRequest
- /
- HeightRequest
- where sizes are known to reduce measure passes.
- CollectionView and ListView
- Use
- ItemSizingStrategy="MeasureFirstItem"
- on
- CollectionView
- when items have uniform height — avoids measuring every item individually.
- <
- CollectionView
- ItemSizingStrategy
- =
- "
- MeasureFirstItem
- "
- ItemsSource
- =
- "
- {Binding Items}
- "
- >
- Prefer
- CollectionView
- over
- ListView
- for new development.
- Keep
- DataTemplate
- visual trees shallow — fewer nested layouts per item.
- Image Optimization
- Size images to display resolution
- — don't load a 4000×3000 image for a 200×200 display.
- Use
- Aspect="AspectFill"
- or
- AspectFit
- and set explicit dimensions.
- Cache downloaded images
- :
- CachingEnabled="True"
- (default) on
- UriImageSource
- , set
- CacheValidity
- .
- Use platform-appropriate formats (WebP for Android, HEIF/PNG for iOS).
- For icons and simple graphics, prefer SVG or vector-based font icons.
- Resource Dictionaries
- App-level
- (
- App.xaml
- ): Shared styles, colors, converters used across multiple pages.
- Page-level
-
- Styles/resources specific to a single page — keeps App.xaml lean.
- Avoid duplicating resources across dictionaries.
- Use
- MergedDictionaries
- to organize large resource sets without bloating a single file.
- Startup Optimization
- Minimize work in
- App
- constructor and
- MainPage
- constructor.
- Defer non-essential service registration — use lazy initialization where possible.
- Reduce the number of XAML pages parsed at startup (use
- Shell
- routing for deferred loading).
- Remove unused
- Handlers
- /
- Effects
- registrations from
- MauiProgram.cs
- .
- On Android, ensure
- AndroidManifest.xml
- doesn't force unnecessary permissions checks at launch.
- Trimming
- Enable IL trimming to reduce app size and remove unused code:
- <
- PropertyGroup
- >
- <
- PublishTrimmed
- >
- true
- </
- PublishTrimmed
- >
- <
- TrimMode
- >
- full
- </
- TrimMode
- >
- </
- PropertyGroup
- >
- Test thoroughly — trimming can remove code accessed only via reflection.
- Use
- [DynamicDependency]
- or
- [UnconditionalSuppressMessage]
- to preserve reflection targets.
- Compiled bindings are essential — reflection-based bindings will be trimmed away.
- NativeAOT
- NativeAOT compiles to native code ahead-of-time for faster startup and smaller footprint.
- Requirements
- compiled bindings, no unconstrained reflection, trimming-compatible code.
<
PropertyGroup
< PublishAot
true </ PublishAot
< PublishTrimmed
true </ PublishTrimmed
</ PropertyGroup
Audit third-party NuGet packages for trimming/AOT compatibility. Use [JsonSerializable] source generators instead of reflection-based JSON serialization. Run dotnet publish with AOT to verify no warnings before shipping. Quick Checklist ✅ x:DataType on all pages, templates, and data-bound views ✅ No nested single-child layouts ✅ Grid preferred over nested StackLayouts ✅ Images sized to display, caching enabled ✅ ItemSizingStrategy="MeasureFirstItem" on uniform CollectionViews ✅ Startup work minimized and deferred ✅ Trimming enabled and tested ✅ Profile with dotnet-trace before and after changes
maui-performance
安装
npx skills add https://github.com/davidortinau/maui-skills --skill maui-performance