B&W print-friendly diagrams + tinkerpop-0001 + wave-3 proof sections. Squash of 94 local commits onto remote master.
49 lines
1.4 KiB
Markdown
49 lines
1.4 KiB
Markdown
# 0004 — Dependencies$GraphDependencies$Node: List.contains() dedup on every addDependency()
|
||
|
||
**Status:** open
|
||
**Severity:** performance — low-medium
|
||
**Component:** `jdk.compiler / com.sun.tools.javac.util.Dependencies$GraphDependencies$Node`
|
||
|
||
---
|
||
|
||
## Root Cause
|
||
|
||
`Dependencies.java:199`:
|
||
|
||
```java
|
||
void addDependency(DependencyKind depKind, Node dep) {
|
||
List<Node> deps = depsByKind.get(depKind);
|
||
if (!deps.contains(dep)) { // O(N) linear scan before every add
|
||
deps.add(dep);
|
||
}
|
||
}
|
||
```
|
||
|
||
`deps` is a `java.util.ArrayList<Node>`. The deduplication check scans the entire list on every `addDependency()` call. Should be a `LinkedHashSet` (O(1) add with deduplication, preserves insertion order).
|
||
|
||
---
|
||
|
||
## Fix
|
||
|
||
```java
|
||
// Replace ArrayList with LinkedHashSet in Node constructor:
|
||
EnumMap<CompletionCause, Set<Node>> depsByKind; // Set, not List
|
||
|
||
Node(ClassSymbol value) {
|
||
super(value);
|
||
this.depsByKind = new EnumMap<>(CompletionCause.class);
|
||
for (CompletionCause depKind : CompletionCause.values()) {
|
||
depsByKind.put(depKind, new LinkedHashSet<>()); // O(1) add + dedup
|
||
}
|
||
}
|
||
|
||
void addDependency(DependencyKind depKind, Node dep) {
|
||
depsByKind.get(depKind).add(dep); // dedup is free, no contains() needed
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Context
|
||
|
||
`GraphDependencies` is only active when the `debug.completionDeps` option is set (disabled by default). Impact is limited to debug/diagnostic compilation runs. Severity lower than 0001–0003.
|