You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@maven.apache.org by "cstamas (via GitHub)" <gi...@apache.org> on 2026/06/08 11:19:37 UTC
[PR] Create simple JMH benchmark to compare CCR and PCR [maven-resolver]
cstamas opened a new pull request, #1908:
URL: https://github.com/apache/maven-resolver/pull/1908
A simple JMH benchmark that compares classic and path conflict resolvers.
--
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: issues-unsubscribe@maven.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Create simple JMH benchmark to compare CCR and PCR [maven-resolver]
Posted by "gnodet (via GitHub)" <gi...@apache.org>.
gnodet commented on PR #1908:
URL: https://github.com/apache/maven-resolver/pull/1908#issuecomment-4652055593
Nice benchmark! A few observations and a suggestion for a more representative topology.
## Minor issues in the current code
1. **`makeDependencyNode(String, String, String, String scope)` silently drops `scope`** — it delegates to the 3-arg overload which then calls the 5-arg one with `null` classifier and hardcoded `"compile"`. The `scope` parameter is never used. Either remove that overload or fix the delegation chain.
2. **`DUMPER_SOUT` is declared but never used** — leftover from debugging.
3. **Assertions in `@Benchmark` hot path** — `assertSame`, `assertEquals`, `assertNotNull` in `uniqueSnake`/`uniqueSnakeWithRootCycle` add overhead to every benchmark invocation. Fine for correctness validation but they do inflate the measurements slightly.
## The "diamond" topology would better stress conflict resolution
The current `uniqueSnake` topology has **zero real conflicts** — every artifact is unique, so both resolvers spend most of their time on bookkeeping with nothing to actually resolve. This actually understates PCR's advantage: PCR's O(N) vs CCR's O(N²) comes from CCR re-walking the whole graph once per conflict group, so real conflicts are needed to expose the difference.
A diamond (or wide diamond fan) is the classic Maven conflict topology — the same artifact pulled in at different versions via two or more paths:
```
root
/ \
left right
| \ / |
| \/ |
| shared-1.0
| \
| shared-2.0 ← conflict! classic "nearest wins" scenario
...
```
Here's a `diamondFan(depth, width)` topology to add — `width` independent chains all pulling in the same shared artifact at conflicting versions:
```java
/**
* A "diamond fan": {@code width} independent chains of length {@code depth}, all converging
* on the same shared artifact at two different versions (simulating a real version conflict).
* This is the topology where CCR's O(N²) re-walk per conflict group shows up most clearly.
*
* Graph shape (width=3, depth=2):
* root
* ├── chain-0-0 → chain-0-1 → shared:1.0
* ├── chain-1-0 → chain-1-1 → shared:2.0 (conflict: 1.0 vs 2.0)
* └── chain-2-0 → chain-2-1 → shared:1.0
*/
private static void diamondFan(ConflictResolver conflictResolver, int depth, int width)
throws RepositoryException {
DependencyNode root = makeDependencyNode("group-id", "root", "1.0");
List<DependencyNode> chains = new ArrayList<>(width);
for (int w = 0; w < width; w++) {
DependencyNode chainHead = makeDependencyNode("group-id", "chain-" + w + "-0", "1.0");
DependencyNode last = chainHead;
for (int d = 1; d < depth; d++) {
DependencyNode dep = makeDependencyNode("group-id", "chain-" + w + "-" + d, "1.0");
last.setChildren(mutableList(dep));
last = dep;
}
// All chains converge on the same artifact at alternating versions — real conflict
String version = (w % 2 == 0) ? "1.0" : "2.0";
DependencyNode shared = makeDependencyNode("group-id", "shared", version);
last.setChildren(mutableList(shared));
chains.add(chainHead);
}
root.setChildren(chains);
DependencyNode result = transform(conflictResolver, root);
assertNotNull(result);
// After conflict resolution, all paths to "shared" must agree on one version
assertEquals(1, countDistinctVersions(result, "shared"));
}
private static int countDistinctVersions(DependencyNode node, String artifactId) {
// BFS/DFS to count distinct versions of the given artifactId in the resolved graph
java.util.Set<String> versions = new java.util.HashSet<>();
collectVersions(node, artifactId, versions);
return versions.size();
}
private static void collectVersions(DependencyNode node, String artifactId, java.util.Set<String> versions) {
if (node.getArtifact() != null && artifactId.equals(node.getArtifact().getArtifactId())
&& node.getData().get(ConflictResolver.NODE_DATA_WINNER) == null) {
versions.add(node.getArtifact().getVersion());
}
for (DependencyNode child : node.getChildren()) {
collectVersions(child, artifactId, versions);
}
}
```
Then add benchmark methods:
```java
@Benchmark
public void diamondFan_10x5_path() throws RepositoryException {
diamondFan(path, 5, 10);
}
@Benchmark
public void diamondFan_10x5_classic() throws RepositoryException {
diamondFan(classic, 5, 10);
}
@Benchmark
public void diamondFan_20x10_path() throws RepositoryException {
diamondFan(path, 10, 20);
}
@Benchmark
public void diamondFan_20x10_classic() throws RepositoryException {
diamondFan(classic, 10, 20);
}
```
My expectation is that `diamondFan` will show a **larger** PCR advantage than `uniqueSnake`, because CCR re-walks the entire graph for the `shared` conflict group (finding it at the tip of every chain), while PCR already has it pre-indexed in its partition map from the initial build pass.
Would be interesting to see your numbers on this one!
--
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: issues-unsubscribe@maven.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Create simple JMH benchmark to compare CCR and PCR [maven-resolver]
Posted by "cstamas (via GitHub)" <gi...@apache.org>.
cstamas merged PR #1908:
URL: https://github.com/apache/maven-resolver/pull/1908
--
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: issues-unsubscribe@maven.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org