Add MIBC profile generator for InitializeComponent methods#34660
Add MIBC profile generator for InitializeComponent methods#34660jkoritzinsky wants to merge 2 commits intodotnet:mainfrom
Conversation
Add a build tool that scans compiled MAUI assemblies for all InitializeComponent* methods (InitializeComponent, InitializeComponentRuntime, InitializeComponentXamlC, InitializeComponentSourceGen) and produces a MIBC profile file consumable by crossgen2 and the .NET AOT compiler for PGO. The tool is integrated into the MSBuild pipeline via the _MauiGenerateMibcProfile target, which runs after XamlC and is opt-in via the MauiGenerateMibcProfile property. The generated file is exposed as the @(MauiMibcProfile) MSBuild item for downstream consumption. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34660Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34660" |
|
Hey there @@jkoritzinsky! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
There was a problem hiding this comment.
Pull request overview
Adds a new build-time tool and MSBuild integration to generate a MIBC profile containing all InitializeComponent* methods from compiled MAUI assemblies, intended to enable partial R2R for XAML-generated code paths.
Changes:
- Add
MibcProfileGeneratorconsole tool that scans assemblies viaSystem.Reflection.Metadataand emits a MIBC PE (optionally compressed). - Add
_MauiGenerateMibcProfileMSBuild target to run the tool afterXamlCand feed the output intoPublishReadyToRunPgoFiles/ crossgen2--partial. - Package the tool alongside existing Controls build tasks for transitive consumption.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets | Adds opt-in target to generate a .mibc and adjust crossgen2 args for partial compilation. |
| src/Controls/src/Build.Tasks/MibcProfileGenerator/Program.cs | Implements the assembly scanner and MIBC emitter. |
| src/Controls/src/Build.Tasks/MibcProfileGenerator/MibcProfileGenerator.csproj | New net10.0 tool project definition + local copy target. |
| src/Controls/src/Build.Tasks/Controls.Build.Tasks.csproj | Wires tool into build tasks packaging (adds project reference + packed outputs). |
...ontrols/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets
Outdated
Show resolved
Hide resolved
...ontrols/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets
Outdated
Show resolved
Hide resolved
...ontrols/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets
Outdated
Show resolved
Hide resolved
src/Controls/src/Build.Tasks/MibcProfileGenerator/MibcProfileGenerator.csproj
Show resolved
Hide resolved
- Add explicit ret instructions to group and AssemblyDictionary IL methods - Fix nested type namespace resolution (walk to outermost declaring type) - Include deps.json in NuGet package and local dev copy - Fix comment to match actual property/item names - Fix indentation to use tabs consistently in targets file Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| Runs after XamlC so the IL has been post-processed and method signatures are final. | ||
| Produces a $(_MauiMibcProfilePath) file and adds it to the @(PublishReadyToRunPgoFiles) item. --> | ||
| <Target Name="_MauiGenerateMibcProfile" | ||
| AfterTargets="XamlC" |
There was a problem hiding this comment.
The XamlC target should not run eventually (hopefully already in .NET 11) and XAML code should be compiled just via the source generator by default. In that case, we should make sure this runs after CoreCompile instead.
| <PropertyGroup> | ||
| <PublishReadyToRunCrossgen2ExtraArgs>$(PublishReadyToRunCrossgen2ExtraArgs) --partial</PublishReadyToRunCrossgen2ExtraArgs> | ||
| </PropertyGroup> |
There was a problem hiding this comment.
There's a different spot in the MAUI SDK which turns on partial R2R - it's the default whenever R2R is enabled (which is also the default). I don't think we should enforce partial here and allow devs to disable it via $(_MauiPublishReadyToRunPartial)=false. Maybe we could actually use that property to skip this task.
There was a problem hiding this comment.
@simonrozsival where is that? I only see that in src/Workload/Microsoft.Maui.Sdk/Sdk/Microsoft.Maui.Sdk.Before.targets which only works for Windows today and doesn't turn on partial R2R.
| <_MibcProfileGeneratorPath>$(MSBuildThisFileDirectory)MibcProfileGenerator.dll</_MibcProfileGeneratorPath> | ||
| </PropertyGroup> | ||
|
|
||
| <Exec Command="dotnet exec "$(_MibcProfileGeneratorPath)" "$(_MauiMibcProfilePath)" "$(IntermediateOutputPath)$(TargetFileName)"" /> |
There was a problem hiding this comment.
I wonder why we explicitly dotnet exec here instead of turning this into a custom MSBuild task?
There was a problem hiding this comment.
System.Reflection.Metadata is a very finicky dependency to get right for MSBuild. Also having a separate tool enables me (or rather Copilot) to more easily validate the tool with ad-hoc testing.
| "InitializeComponentRuntime", | ||
| "InitializeComponentXamlC", | ||
| "InitializeComponentSourceGen", |
There was a problem hiding this comment.
In Release builds, only the InitializeComponent method is relevant. The other 3 are used only for unit testing, when we need to generate all 3 versions at build time and switch between them at runtime.
There was a problem hiding this comment.
unit testing, and full page XamlHotReload. But as @simonrozsival said, in Release builds, only InitializeComponent should be present
|
@jkoritzinsky I really like this. I think this is a great start and once we have this task that generates an app-specific profile based on static analysis, we can experiment with including more than just For example, we were thinking about changing the way we generate the "inflator" code to be split between smaller methods (https://github.com/dotnet/maui/pull/31555/changes#diff-d1e4f87785dfbad698ce654733169bf7e6091581ccebdbada7f5e66460b17bfcR166-R224) which allowed us to generate much more efficient code which showed in benchmarks. If we wanted to do that, we should also update One other thing we discussed internally some time ago was that maybe we should simply R2R anything in the app-specific .dlls. They are usually quite small compared to the BCL + MAUI SDK and Android/iOS bindings, so just naively compiling everything should not increase the app bundle too much and it would make sure we don't need to JIT any of the app code at startup. |
|
The description of this PR might be a bit misleading since it says it's for Debug builds. If I read the code correctly it will work for both. In reality this doesn't make much sense for Debug builds - we will not R2R the application in Debug builds because it would hurt built time, and I think the cost of running crossgen is larger than the startup gain it provides. Additionally, we don't have the ability to debug R2R code, so we can't really R2R the app itself anyway. For Release builds this would make a lot of sense. The prime example of code this can help with is XAML inflation - which is the XAML inflation is responsibility of the XSG (XAML Source Gen), thus that's the component with the best knowledge of what methods would benefit from being R2R. Personally, I think it would be even better if we could introduce some attribute which XSG puts on certain methods and that would tell this new tool to include those methods in the MIBC file. @StephaneDelcroix what do you think? |
Thanks for this, I love what you're doing there a few thoughts:
|
|
The idea of this tool is to run only in Debug builds. @vitek-karas this tool only makes sense for Debug builds, as for Release these methods should already be included in R2R unless MAUI's existing partial R2R support doesn't include the user's app assembly or the XAML code. If the Release configuration currently doesn't include the XAML code and we want it to do so, then this becomes interesting for Release. @StephaneDelcroix is our goal for the Debug experience lowest build time or lowest F5 (build time + startup time to first page)? This PR is meant to improve the overall F5 time by spending a little more time in build to get a lot faster startup. If that's not what we want to optimize for (or this tool does not achieve it) then it's not worth adding. I'll update this tool to run after CoreCompile as well to catch the debug scenario. |
Summary
Adds a build tool that generates MIBC (Managed Instrumented Binary Code) profile files listing all
InitializeComponent*methods from compiled MAUI assemblies. These files do not have any actual profile data, but they can be consumed by crossgen2 for partial compilation. Also add MSBuild targets to enable partial R2R for just XAML-generated code in Debug builds for CoreCLR targets using said tool to provide a faster experience for XAML loading in Debug using said MIBC files.What's included
MibcProfileGenerator tool (src/Controls/src/Build.Tasks/MibcProfileGenerator/)
A standalone .NET console app that:
InitializeComponent— primary entry pointInitializeComponentRuntime— runtime XAML inflationInitializeComponentXamlC— XamlC IL-compiled pathInitializeComponentSourceGen— source generator compiled path.mibc) and uncompressed (.dll) outputdotnet-pgo dumpMSBuild integration
_MauiGenerateMibcProfileinMicrosoft.Maui.Controls.targetsXamlCso all IL post-processing is completePackaging
_CopyToBuildTasksDirtargetUsage
Automatic in Debug CoreCLR builds.