B&W print-friendly diagrams + tinkerpop-0001 + wave-3 proof sections. Squash of 94 local commits onto remote master.
2.8 KiB
Timeline — java-topology
2026-03-23
Session opened. Sparse shallow clone of jdk.compiler confirmed present. Branch: master.
Investigation started. Searched all .java files for Graph, Topology, graph, topology hits.
Primary targets identified:
util/GraphUtils.java— core graph algorithm libraryutil/Dependencies.java— symbol completion dependency graphcomp/Infer.java— type inference graph solver (uses Tarjan)comp/DeferredAttr.java— stuck expression resolution (uses Tarjan)comp/Modules.java— module graph, transitive closure
Defect confirmed: GraphUtils.java:186 — Tarjan's SCC algorithm uses stack.contains(n) (O(n) linear scan on ListBuffer) instead of n.active (O(1) boolean field that exists on TarjanNode for exactly this purpose). Makes Tarjan O(V²) instead of O(V+E).
Ticket opened: 0001-tarjan-ov2-stack-contains
Tests created: tests/unit/, tests/integration/, tests/functional/ — 74 tests all passing. make -C tests all.
Before/after timing confirmed:
- Algorithm level: 23x speedup at V=800, ~4x growth ratio BEFORE vs ~2x AFTER.
- End-to-end compilation: no measurable difference at typical inference var counts (V=4–6).
2026-03-23 (continued)
Stack-wide defect survey. Fox pointed out the algorithm propagates up the full stack. Extracted all JDK module classes from jimage and scanned bytecode for Deque/List/Stack.contains() in graph/topology/dependency code.
Additional defect sites confirmed:
| Ticket | Location | Defect | Module |
|---|---|---|---|
| 0002 | Infer$GraphSolver$InferenceGraph.findNode() |
O(N) ArrayList scan, called O(N³) total via buildStuckGraph() → canInfluence() |
jdk.compiler |
| 0003 | ModuleHashesBuilder$TopoSorter.visit() |
Deque.contains() for on-stack check — same pattern as 0001, different module |
java.base |
| 0004 | Dependencies$GraphDependencies$Node.addDependency() |
List.contains() dedup on every add |
jdk.compiler |
Pattern confirmed: The same O(n) membership check on a linear collection, used where O(1) is possible and a dedicated flag/set already exists or trivially could. Not one bug — a systemic pattern replicated across at least 4 locations in 2 modules.
Cascade analysis:
buildStuckGraph()is O(N³) due to N² calls tocanInfluence(), each doing O(N)findNode()+ uncached O(V+E)closure()— independent of 0001.ModuleHashesBuilderis injava.base— affects everyjlinkbuild.- Fix 0001 alone: algorithm is correct but callers are still slow.
- Fix 0001+0002+0003: full stack improvement.
Next: Tickets for 0002–0004. Additional dot diagrams. Tests for 0002 (closure caching, findNode indexing).