Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[xaml] improve performance in debug-mode (#21460)
* [xaml] improve performance in debug-mode Applies to: #18505 Context: https://github.com/dotnet/maui/files/13251041/MauiCollectionView.zip In reviewing various issues about `CollectionView`, there is a pattern of: * My app is slow (in `Debug` mode) * Oh, but it seems completely OK in `Release`! This is due to several features enabled in `Debug` mode, such as: * On mobile, the Mono interpreter is used (enables C# hot reload) * Xaml compilation is disabled (enables XAML hot reload) * Other debug features are enabled (such as the `$(Optimize)` flag) I attached `dotnet-trace` to the app above on a Pixel 5 while debugging, just to see what I could find. I also had XAML & C# hot reload enabled. One thing that appears when parsing XAML is: 2.11s microsoft.maui.controls.xaml!Microsoft.Maui.Controls.Xaml.ApplyPropertiesVisitor.GetBindableProperty(System.Type,string 257.40ms System.Private.CoreLib!System.String.Format(string,object,object) 172.25ms microsoft.maui.controls!Microsoft.Maui.Controls.Xaml.XamlParseException.FormatMessage(string,System.Xml.IXmlLineInfo) So about ~2 seconds of this app's startup was in `ApplyPropertiesVisitor.GetBindableProperty()`. Looking at what is happening: if (exception == null && bindableFieldInfo == null) { exception = new XamlParseException( Format("BindableProperty {0} not found on {1}", localName + "Property", elementType.Name), lineInfo); } //... if (throwOnError) throw exception; // only use of `exception` But then `throwOnError` is actually `false` in this case, so a `XamlParseException` is created and not used. I could just reorder the logic to avoid creating a `XamlParseException` and calling `Format()`. Next, I noticed the System.Reflection usage: var bindableFieldInfo = elementType.GetFields(supportedFlags) .FirstOrDefault(fi => (fi.IsAssembly || fi.IsPublic) && fi.Name == localName + "Property"); If this were called on many bindable properties on `Label`, `Button`, etc., this code would create lots of `FieldInfo[]` arrays and iterate until a matching property (field) is found. I think we can change this to avoid creating `FieldInfo[]` arrays, such as: var bindableFieldInfo = elementType.GetField(localName + "Property", supportedFlags); if (bindableFieldInfo is not null && (bindableFieldInfo.IsAssembly || bindableFieldInfo.IsPublic)) { //... With these changes in place, it significantly improves the call: 816.35ms microsoft.maui.controls.xaml!Microsoft.Maui.Controls.Xaml.ApplyPropertiesVisitor.GetBindableProperty(System.Type,string Saving over about ~1.3 seconds of startup time in debug mode. This should improve the performance of XAML parsing on all platforms, which is most likely being used while debugging. You *can* disable Xaml compilation in `Release` mode, but it is not recommended. * Update BuildWarningsUtilities.cs * Remove `bool throwOnError = false` parameter
- Loading branch information