gnodet commented on code in PR #1938:
URL: https://github.com/apache/maven-resolver/pull/1938#discussion_r3487878862


##########
maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/PathConflictResolver.java:
##########
@@ -170,28 +167,33 @@ public DependencyNode transformGraph(DependencyNode node, 
DependencyGraphTransfo
                 scopeDeriver.getInstance(node, context),
                 optionalitySelector.getInstance(node, context),
                 conflictIds,
+                sortedConflictIds.size(),
                 node);
 
         // loop over topographically sorted conflictIds
         for (String conflictId : sortedConflictIds) {
-            // paths in given conflict group to consider
-            Set<Path> paths = state.partitions.get(conflictId);
-            if (paths.isEmpty()) {
+            // paths in given conflict group to consider; filter out those 
moved out of scope
+            List<Path> allPaths = state.partitions.get(conflictId);
+            List<Path> activePaths = new ArrayList<>(allPaths.size());
+            List<ConflictItem> items = new ArrayList<>(allPaths.size());
+            for (Path p : allPaths) {
+                if (!p.outOfScope) {
+                    activePaths.add(p);
+                    items.add(new ConflictItem(p));
+                }
+            }
+            if (activePaths.isEmpty()) {

Review Comment:
   Fixed in 0b4ca58. Partition entries are now replaced with the filtered 
`activePaths` list after each conflict group, releasing references to 
out-of-scope paths and their detached subtrees for GC during resolution. 
Additionally, `moveOutOfScope()` now nulls children references on marked nodes 
to break reference chains, and `conflictItemCount` is tracked inline during the 
main loop instead of re-scanning partitions post-resolution.



##########
maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/PathConflictResolver.java:
##########
@@ -610,43 +643,53 @@ private boolean isDirectDependencyOnPathToRoot(Artifact 
artifact) {
          * verbosity mode we remove "redundant" nodes (of a range) leaving 
only "winner equal" loser, that have same GACEV as winner.
          */
         private int relatedSiblingsCount(Artifact artifact, Path parent) {
-            String ga = artifact.getGroupId() + ":" + artifact.getArtifactId();
-            return Math.toIntExact(parent.children.stream()
-                    .map(n -> n.dn.getArtifact())
-                    .filter(a -> ga.equals(a.getGroupId() + ":" + 
a.getArtifactId()))
-                    .count());
+            if (parent.children == null) {
+                return 0;
+            }
+            String groupId = artifact.getGroupId();
+            String artifactId = artifact.getArtifactId();
+            int count = 0;
+            for (Path n : parent.children) {
+                Artifact a = n.dn.getArtifact();
+                if (Objects.equals(groupId, a.getGroupId()) && 
Objects.equals(artifactId, a.getArtifactId())) {
+                    count++;
+                }
+            }
+            return count;
         }
 
         /**
-         * Removes this and all child {@link Path} nodes from winner selection 
scope; essentially marks whole subtree
+         * Marks this and all child {@link Path} nodes as out of scope; 
essentially marks whole subtree
          * from "this and below" as loser, to not be considered in subsequent 
winner selections.
-         * Uses {@link LinkedHashSet} for O(1) removal instead of the previous 
O(N) ArrayList.remove.
+         * Uses a boolean flag instead of removing from partition collections, 
avoiding the per-entry
+         * overhead of LinkedHashSet (~48 bytes/entry). Out-of-scope paths are 
filtered at query time.
          */
         private void moveOutOfScope() {
-            this.state.partitions.get(this.conflictId).remove(this);
-            for (Path child : this.children) {
-                child.moveOutOfScope();
+            this.outOfScope = true;
+            if (this.children != null) {
+                for (Path child : this.children) {
+                    child.moveOutOfScope();

Review Comment:
   Fixed in 0b4ca58. Converted `moveOutOfScope()` to use an explicit 
`ArrayList` stack instead of recursion, consistent with the iterative 
`gatherCRNodes()` approach. The iterative version also nulls children 
references on out-of-scope nodes to accelerate GC of detached subtrees.



-- 
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