B&W print-friendly diagrams + tinkerpop-0001 + wave-3 proof sections. Squash of 94 local commits onto remote master.
46 lines
2.8 KiB
Markdown
46 lines
2.8 KiB
Markdown
# 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 library
|
||
- `util/Dependencies.java` — symbol completion dependency graph
|
||
- `comp/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](tickets/0001-tarjan-ov2-stack-contains.md)
|
||
|
||
**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 to `canInfluence()`, each doing O(N) `findNode()` + uncached O(V+E) `closure()` — independent of 0001.
|
||
- `ModuleHashesBuilder` is in `java.base` — affects every `jlink` build.
|
||
- 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).
|