gnodet opened a new pull request, #12540:
URL: https://github.com/apache/maven/pull/12540

   ## Summary
   
   Maven 4's immutable model pattern creates excessive intermediate objects 
during effective model construction, contributing to ~20% more CPU time 
compared to Maven 3. This PR addresses the root causes through 7 optimization 
phases targeting the generated templates and hand-written pipeline code:
   
   ### Changes
   
   **Phase 0 — merger.vm false-positive change detection** (highest impact)
   - String fields: add `src != tgt` reference check before setting on builder 
— prevents defeating `build()` short-circuit when source and target share the 
same string reference (common during inheritance assembly)
   - Boolean/int fields: add value equality check before setting on builder
   - Composite fields (mult=1): add `merged != target.getField()` identity guard
   - List fields: add identity check for merge results
   
   **Phase 1 — model.vm computeLocations() optimization**
   - Replace `Stream.concat().collect(Collectors.toUnmodifiableMap())` with 
direct `HashMap` merge
   - Skip `Map.copyOf()` when old locations map is already immutable from a 
previous `build()`
   
   **Phase 2 — model.vm constructor: skip ImmutableCollections.copy() for base 
fields**
   - When a List/Map field comes unchanged from the base object, reuse it 
directly instead of passing through `ImmutableCollections.copy()` — the base's 
fields are already immutable from a previous `build()`
   
   **Phase 3 — DefaultModelNormalizer: avoid always-build pattern**
   - `mergeDuplicates()`: only create builder and call `build()` when duplicate 
plugins/dependencies are actually found
   - `injectDefaultValues()`: only build when scope injection changes something
   - `injectPlugin()`: skip rebuild when plugin dependencies don't need scope 
injection
   
   **Phase 4 — DefaultProfileInjector: guard sub-object rebuilds**
   - Add `newBuild != build` identity check before setting Build on 
Model.Builder
   
   **Phase 5 — DefaultModelBuilder: replace nested with*() chains**
   - Replace patterns like `model.withParent(parent.withRelativePath(x))` (2 
full immutable copies) with single-builder patterns
   - Consolidate `withProfiles(List.of()).withParent(null)` into single builder 
call
   - Add identity check before `withPomFile()`
   
   **Phase 6 — DefaultPluginConfigurationExpander: skip unchanged rebuilds**
   - Check if plugin expansion actually changed anything before rebuilding 
Build/Model objects
   - Original code unconditionally called `model.withBuild(build)` even when 
nothing expanded
   
   **Phase 7 — ImmutableCollections.copy(Map): detect JDK unmodifiable maps**
   - `copy(Map)` only recognized custom `AbstractImmutableMap` as 
already-immutable
   - Now also recognizes JDK internal unmodifiable maps (`Map.of()`, 
`Map.copyOf()`) to avoid redundant wrapping
   
   ### Impact
   
   These changes target the ~16-20 intermediate `Model` objects created per POM 
during `buildEffectiveModel()` / `readEffectiveModel()`. The `build()` 
short-circuit (`if base != null && all fields unchanged → return base`) was 
being defeated by false-positive field assignments in the merger, causing 
unnecessary object allocation chains (Model → Build → Plugin → Dependency → 
...).
   
   Profiling data (JDK 25 JFR on Apache Camel, ~1000 modules):
   - Maven 4 user CPU: ~36s vs Maven 3: ~30s (~20% overhead)
   - Primary allocation sites: `MavenMerger.merge*` → `Builder.build()` → 
constructor → `ImmutableCollections.copy()` + `computeLocations()`
   
   ## Test plan
   
   - [x] `mvn test -pl impl/maven-impl` — 466 tests pass, 0 failures
   - [x] `mvn test -pl compat/maven-model-builder` — 166 tests pass, 0 failures
   - [x] `mvn test -pl impl/maven-core` — 549 pass (5 pre-existing failures on 
master)
   - [ ] Full CI verification
   
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to