[TrimmableTypeMap] Improve incremental build performance#12229
Open
simonrozsival wants to merge 3 commits into
Open
[TrimmableTypeMap] Improve incremental build performance#12229simonrozsival wants to merge 3 commits into
simonrozsival wants to merge 3 commits into
Conversation
Preserve unchanged post-trim Java outputs, prevent pre-trim generation from clobbering linked metadata, and make the legacy post-trimming pipeline incremental. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a301fa68-0e6c-4280-b2f2-bc3d4c9ae3de
Contributor
There was a problem hiding this comment.
Pull request overview
Improves incremental build performance for the Trimmable TypeMap pipeline (CoreCLR trimmed builds) by avoiding unnecessary Java churn, correcting output ownership for post-trim generated files, and making the legacy llvm-ir post-trimming pipeline incremental.
Changes:
- Updates post-trim linked-Java generation to be incremental and recover missing outputs, with explicit tracking of the expected linked-Java output set.
- Fixes output ownership so pre-trim generation doesn’t overwrite post-trim
acw-map.txt/ApplicationRegistration.java, and makes_GenerateJavaStubsreact to both pre- and post-trim producer stamps. - Makes
llvm-ir_PostTrimmingPipelineincremental via explicit inputs/outputs and a separate collector target; adds/extends test coverage around these behaviors.
Show a summary per file
| File | Description |
|---|---|
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs | Adds incremental/recovery tests for post-trim linked-Java outputs and verifies Java toolchain targets remain skipped when appropriate. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GenerateTrimmableTypeMapTests.cs | Adds a regression test ensuring failing in-place updates don’t prune last-known-good outputs; extends test harness to collect errors. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs | Extends incremental test expectations to include _PostTrimmingPipeline behavior for CoreCLR. |
| src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs | Adjusts stale-Java pruning behavior to avoid deleting outputs when generation has logged errors. |
| src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets | Updates stamp/input wiring and prevents pre-trim generator from overwriting post-trim-owned outputs; records linked-Java file list as a tracked write. |
| src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets | Adds stamp invalidation when linked-Java outputs are missing/unexpected; switches post-trim generation to in-place updates and persists expected output list. |
| src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.LlvmIr.targets | Makes _PostTrimmingPipeline incremental with explicit inputs/outputs, plus a collector target; ensures Deterministic participates in the property cache. |
| src/Microsoft.Android.Sdk.TrimmableTypeMap/README.md | Updates documentation to reflect the new incremental stamp ownership model and in-place linked-Java behavior. |
Copilot's findings
Comments suppressed due to low confidence (1)
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets:129
linked-java-files.txtcurrently records the raw@(_PostTrimGeneratedJavaFiles)item values. To make the subsequent validation resilient across OS path separators and relative/absolute differences, it should persist a normalized form (e.g.,%(FullPath)) that matches what MSBuild produces from globbing.
<WriteLinesToFile
File="$(_PostTrimTypeMapJavaFilesList)"
Lines="@(_PostTrimGeneratedJavaFiles)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />
- Files reviewed: 8/8 changed files
- Comments generated: 2
Reuse persisted TypeMap and Java output lists, and skip unchanged CoreCLR shrunk-assembly copies while retaining NativeAOT remapping behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a301fa68-0e6c-4280-b2f2-bc3d4c9ae3de
Persist and compare fully qualified Java paths and normalize the post-trim output base directory for reliable Windows incrementality. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a301fa68-0e6c-4280-b2f2-bc3d4c9ae3de
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
acw-map.txtandApplicationRegistration.javaa single post-trim owner_GenerateJavaStubsreact independently to pre-trim manifest changes and post-trim Java changesllvm-irpost-trimming assembly pipeline incrementalMotivation
On a Release CoreCLR
dotnet new maui --sample-contentapp, an ordinary managed source touch caused the trimmable path to delete and recreate all 566 linked JCWs. Their new timestamps forced javac and D8 to rebuild identical output:llvm-irWith the generic universal-APK no-op fix from #12230 applied, the additional
trimmable-specific no-op changes in this PR reduce repeated
dotnet buildfrom 4.58 seconds to approximately 3.0-3.5 seconds:
typemap-assemblies.txtfor ILLink inputsFileWritesThe manifest case also exposed an output-ownership bug. The pre-trim pass overwrote the final post-trim files while the post-trim target remained up to date:
acw-map.txtApplicationRegistration.javaThe overwritten registration source additionally registered
android.app.Application, and its changed timestamp triggered javac and D8.Implementation
linked-java._GenerateJavaStubsdepends on both producer stamps: pre-trim for the manifest/shared outputs and post-trim for linked JCWs.linked-java-files.txtrecords the expected JCW set. Missing or unexpected Java files, a missing ACW map, or a missing registration source invalidate the post-trim stamp._PostTrimmingPipelinenow has explicit inputs/outputs while a separate collector target continues to repopulate its dynamic assembly items._AddTrimmableTypeMapToLinkerconsumestypemap-assemblies.txtinstead of wildcarding the output directory.java-files.txtandlinked-java-files.txtdrive no-opFileWrites; migration fallbacks preserve outputs from olderobjtrees.Validation
Build_WithTrimmableTypeMap_PublishTrimmed_IncrementalChangesAvoidUnnecessaryJavaWorkBuild_WithTrimmableTypeMap_PublishTrimmed_PostTrimJavaGenerationIsIncrementalBuild_WithTrimmableTypeMap_PublishTrimmed_DeletesStaleLinkedJavaWhenLinkedJavaShrinksExecute_MissingJavaSource_DoesNotPruneExistingOutputBuild_WithTrimmableTypeMap_MissingJavaListPreservesGeneratedJavaBuild_WithTrimmableTypeMap_PublishTrimmed_MissingLinkedJavaListRegeneratesBuild_WithTrimmableTypeMap_IncrementalBuildAfterILLinkAdditionalStepsIsSkippedOnSecondBuildllvm-irapps launched and survived 100 Monkey eventsFollow-up
Clean trimmable builds still carry 85 managed TypeMap DLLs through ILLink,
ProcessAssemblies, compression, and packaging; 49 are empty stubs. Reducing that file fan-out is a separate, larger optimization.Related to #12184