The Pass-2 topological level assignment in cmdPhasePlanIndex dequeued its Kahn's-algorithm queue with Array.shift(), which is O(n) per call in V8, so the BFS was O(V^2) and slowed superlinearly on deep queues (wide fan-in plan graphs). Extract the traversal into a pure, exported computeDependencyLevels (rawPlans, planMap, canonicalToId) and dequeue via a head index (queue[head++]) -> O(V+E). Behavior is identical: same FIFO order, same longest-path levels, same visited-count cycle detection. A complexity-contract comment above the loop documents why shift() must not be reintroduced. Adds tests/phase-dependency-levels.test.cjs with deterministic behavior and edge-case coverage (linear chain, diamond longest-path, independent set, cycle, canonical-prefix resolution, empty, self-loop, duplicate edge, external dep). A timing-based complexity guard was intentionally omitted: the O(V+E) Map-build constant dilutes the O(V^2) signal until impractical N (~1e6), so an empirical guard is inherently flaky on contended CI — the contract is enforced by the inline comment and correctness tests instead. Fixes #307 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
5
.changeset/jolly-moles-climb.md
Normal file
5
.changeset/jolly-moles-climb.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
type: Fixed
|
||||
pr: 383
|
||||
---
|
||||
Phase dependency level assignment (gsd-tools phase-plan-index) now dequeues its Kahns-algorithm BFS via a head index instead of Array.shift(), fixing O(V^2) behavior that slowed superlinearly on wide fan-in plan graphs (Array.shift() is O(n) per call in V8). Now O(V+E); behavior is unchanged (same topological levels, same cycle detection). Fixes #307.
|
||||
Reference in New Issue
Block a user