maui-performance
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese.NET MAUI Performance Optimization
.NET MAUI 性能优化
Profiling
性能分析
- dotnet-trace: Cross-platform profiler for all MAUI targets. Collect traces with:
shell
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.
- dotnet-trace:适用于所有MAUI目标平台的跨平台性能分析器。使用以下命令收集跟踪数据:
shell
dotnet-trace collect --process-id <PID> --providers Microsoft-DotNETCore-SampleProfiler - PerfView(仅Windows):用于WinUI目标平台的深度内存分配和CPU分析。
- 优化前先做性能分析——用数据说话,不要凭猜测。
Compiled Bindings
编译绑定
- Always set on pages/views to enable compiled bindings.
x:DataType - Compiled bindings are 8–20× faster than reflection-based bindings.
- Required for NativeAOT and full trimming — reflection bindings break under trimming.
- Apply at the highest reasonable scope (page or root element).
x:DataType
xml
<ContentPage xmlns:vm="clr-namespace:MyApp.ViewModels"
x:DataType="vm:MainViewModel">
<Label Text="{Binding Title}" />
</ContentPage>- For inside
DataTemplate/CollectionView, setListViewon the template root:x:DataType
xml
<DataTemplate x:DataType="model:Item">
<Label Text="{Binding Name}" />
</DataTemplate>- Minimize unnecessary bindings: Static content that never changes doesn't need . Use literal values or
{Binding}instead.x:Static
- 始终在页面/视图上设置以启用编译绑定。
x:DataType - 编译绑定的速度比基于反射的绑定快8-20倍。
- 这是NativeAOT和完全代码裁剪的必要条件——基于反射的绑定在裁剪后会失效。
- 在尽可能高的作用域(页面或根元素)上应用。
x:DataType
xml
<ContentPage xmlns:vm="clr-namespace:MyApp.ViewModels"
x:DataType="vm:MainViewModel">
<Label Text="{Binding Title}" />
</ContentPage>- 对于/
CollectionView中的ListView,在模板根元素上设置DataTemplate:x:DataType
xml
<DataTemplate x:DataType="model:Item">
<Label Text="{Binding Name}" />
</DataTemplate>- 减少不必要的绑定:永远不会变化的静态内容不需要使用,改用字面量值或
{Binding}。x:Static
Layout Optimization
布局优化
- Avoid nested single-child layouts — a with one child is pointless overhead.
StackLayout - Prefer over nested
Grid/StackLayout— Grid resolves layout in a single pass.VerticalStackLayout - Use to hide elements rather than adding/removing from the tree at runtime.
IsVisible="False" - Remove unnecessary wrapper containers — every layout adds a measure/arrange pass.
- Avoid when
AbsoluteLayoutwith row/column definitions achieves the same result.Grid - Set explicit /
WidthRequestwhere sizes are known to reduce measure passes.HeightRequest
- 避免嵌套单元素布局——仅包含一个子元素的会造成无意义的性能开销。
StackLayout - 优先使用而非嵌套的
Grid/StackLayout——Grid只需一次遍历即可完成布局计算。VerticalStackLayout - 使用隐藏元素,而非在运行时从布局树中添加/移除元素。
IsVisible="False" - 移除不必要的包装容器——每个布局都会增加一次测量/排列的开销。
- 当使用带行列定义的可以实现相同效果时,避免使用
Grid。AbsoluteLayout - 在已知尺寸的元素上设置明确的/
WidthRequest,以减少测量次数。HeightRequest
CollectionView and ListView
CollectionView 与 ListView
- Use on
ItemSizingStrategy="MeasureFirstItem"when items have uniform height — avoids measuring every item individually.CollectionView
xml
<CollectionView ItemSizingStrategy="MeasureFirstItem"
ItemsSource="{Binding Items}">- Prefer over
CollectionViewfor new development.ListView - Keep visual trees shallow — fewer nested layouts per item.
DataTemplate
- 当中的项具有统一高度时,设置
CollectionView——避免逐个测量每个项。ItemSizingStrategy="MeasureFirstItem"
xml
<CollectionView ItemSizingStrategy="MeasureFirstItem"
ItemsSource="{Binding Items}">- 新开发优先使用而非
CollectionView。ListView - 保持的视觉树层级简洁——每个项的嵌套布局越少越好。
DataTemplate
Image Optimization
图片优化
- Size images to display resolution — don't load a 4000×3000 image for a 200×200 display.
- Use or
Aspect="AspectFill"and set explicit dimensions.AspectFit - Cache downloaded images: (default) on
CachingEnabled="True", setUriImageSource.CacheValidity - Use platform-appropriate formats (WebP for Android, HEIF/PNG for iOS).
- For icons and simple graphics, prefer SVG or vector-based font icons.
- 根据显示分辨率调整图片尺寸——不要为200×200的显示区域加载4000×3000的图片。
- 使用或
Aspect="AspectFill"并设置明确的尺寸。AspectFit - 缓存下载的图片:默认启用
UriImageSource,可设置CachingEnabled="True"。CacheValidity - 使用平台适配的格式(Android用WebP,iOS用HEIF/PNG)。
- 对于图标和简单图形,优先使用SVG或基于矢量的字体图标。
Resource Dictionaries
资源字典
- App-level (): Shared styles, colors, converters used across multiple pages.
App.xaml - Page-level: Styles/resources specific to a single page — keeps App.xaml lean.
- Avoid duplicating resources across dictionaries.
- Use to organize large resource sets without bloating a single file.
MergedDictionaries
- 应用级():存放多页面共享的样式、颜色、转换器。
App.xaml - 页面级:存放仅单个页面使用的样式/资源——保持App.xaml简洁。
- 避免在多个字典中重复定义资源。
- 使用组织大型资源集合,避免单个文件过于臃肿。
MergedDictionaries
Startup Optimization
启动优化
- Minimize work in constructor and
Appconstructor.MainPage - Defer non-essential service registration — use lazy initialization where possible.
- Reduce the number of XAML pages parsed at startup (use routing for deferred loading).
Shell - Remove unused /
Handlersregistrations fromEffects.MauiProgram.cs - On Android, ensure doesn't force unnecessary permissions checks at launch.
AndroidManifest.xml
- 减少构造函数和
App构造函数中的操作。MainPage - 延迟非必要的服务注册——尽可能使用延迟初始化。
- 减少启动时解析的XAML页面数量(使用路由实现延迟加载)。
Shell - 从中移除未使用的
MauiProgram.cs/Handlers注册。Effects - 在Android上,确保不会在启动时强制进行不必要的权限检查。
AndroidManifest.xml
Trimming
代码裁剪
Enable IL trimming to reduce app size and remove unused code:
xml
<PropertyGroup>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>full</TrimMode>
</PropertyGroup>- Test thoroughly — trimming can remove code accessed only via reflection.
- Use or
[DynamicDependency]to preserve reflection targets.[UnconditionalSuppressMessage] - Compiled bindings are essential — reflection-based bindings will be trimmed away.
启用IL裁剪以减小应用体积并移除未使用的代码:
xml
<PropertyGroup>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>full</TrimMode>
</PropertyGroup>- 彻底测试——裁剪可能会移除仅通过反射访问的代码。
- 使用或
[DynamicDependency]保留反射目标。[UnconditionalSuppressMessage] - 编译绑定是必要条件——基于反射的绑定会被裁剪掉。
NativeAOT
NativeAOT
- NativeAOT compiles to native code ahead-of-time for faster startup and smaller footprint.
- Requirements: compiled bindings, no unconstrained reflection, trimming-compatible code.
xml
<PropertyGroup>
<PublishAot>true</PublishAot>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>- Audit third-party NuGet packages for trimming/AOT compatibility.
- Use source generators instead of reflection-based JSON serialization.
[JsonSerializable] - Run with AOT to verify no warnings before shipping.
dotnet publish
- NativeAOT提前编译为原生代码,实现更快的启动速度和更小的内存占用。
- 要求:使用编译绑定、无无约束反射、代码兼容裁剪。
xml
<PropertyGroup>
<PublishAot>true</PublishAot>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>- 检查第三方NuGet包是否兼容裁剪/AOT。
- 使用源生成器替代基于反射的JSON序列化。
[JsonSerializable] - 发布前使用命令结合AOT进行验证,确保无警告。
dotnet publish
Quick Checklist
快速检查清单
- ✅ on all pages, templates, and data-bound views
x:DataType - ✅ No nested single-child layouts
- ✅ Grid preferred over nested StackLayouts
- ✅ Images sized to display, caching enabled
- ✅ on uniform CollectionViews
ItemSizingStrategy="MeasureFirstItem" - ✅ Startup work minimized and deferred
- ✅ Trimming enabled and tested
- ✅ Profile with dotnet-trace before and after changes
- ✅ 所有页面、模板和数据绑定视图都已设置
x:DataType - ✅ 无嵌套单元素布局
- ✅ 优先使用Grid而非嵌套StackLayout
- ✅ 图片已按显示尺寸调整,缓存已启用
- ✅ 统一高度的CollectionView已设置
ItemSizingStrategy="MeasureFirstItem" - ✅ 启动时的操作已最小化并延迟执行
- ✅ 已启用代码裁剪并完成测试
- ✅ 优化前后均使用dotnet-trace进行性能分析