Skip to content

Rewrite dependency resolution using algebraic-graphs#2

Merged
ocharles merged 2 commits into
masterfrom
algebraic-graphs-rewrite
Jul 15, 2026
Merged

Rewrite dependency resolution using algebraic-graphs#2
ocharles merged 2 commits into
masterfrom
algebraic-graphs-rewrite

Conversation

@ocharles

@ocharles ocharles commented Jul 8, 2026

Copy link
Copy Markdown

We know that dbmigrations has a horrific slowdown with non-linear migration graphs. I've slapped Claude on it and generated a pathological test case in - this takes close to a minute on master, but with this rewrite it's in the order of seconds.

ocharles and others added 2 commits July 8, 2026 17:03
dependenciesWith enumerated every path from the start object (each
object's direct successor names followed by the recursive expansion of
each name), then deduplicated the result with the quadratic cleanLDups.
The number of paths is exponential in the depth of a non-linear
dependency graph, so an upgrade over a "diamond ladder" of just 46
migrations took ~55 seconds.

Produce the identical ordering in linear time by scanning the virtual
path enumeration from the end: walk successor names in reverse order,
expand each name's subtree at most once (a repeated expansion occurs
earlier in the enumeration, so it cannot contain a last occurrence),
and emit each name the first time it is seen, i.e. at its last
occurrence. Like the old code, the traversal is name-driven rather
than node-driven, so behaviour is preserved even for graphs with
duplicate object names.

Also replace the assoc-list lookup in dependenciesWith and the
list-membership filters in migrationsToApply/migrationsToRevert with
Map/Set equivalents.

Add a stress test that simulates the upgrade command over a
diamond-ladder graph (two migrations per level, each depending on both
migrations of the previous level). It now runs in ~3ms where it
previously took ~55s.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the fgl-based dependency graph and the hand-rolled traversal
and cycle detection with algebraic-graphs, which postdates this
library's original design:

- The graph is now an AdjacencyMap keyed by object name, built
  directly with `stars`, so the node-index bookkeeping
  (depGraphObjectMap/depGraphNameMap) disappears.

- dependencies/reverseDependencies are `reachable` + `induce` +
  `topSort` (reverseDependencies via `transpose`). topSort returns the
  lexicographically smallest topological ordering, so results are
  deterministic by construction rather than dependent on graph node
  numbering (i.e. on directory listing order).

- The CycleDetection module is deleted: cycle rejection now comes from
  `topSort`'s Left result, which contains the actual cycle, so
  mkDepGraph can finally report which objects form the cycle
  (resolving the long-standing XXX comment). Its test cases are ported
  to mkDepGraph-level tests.

- mkDepGraph now rejects duplicate object identifiers explicitly.
  Previously duplicates were silently tolerated with confusing
  behaviour (name lookups resolved to the first match while the graph
  contained both vertices).

Ordering semantics: any result is still a valid topological order, but
the specific order changes where siblings were previously ordered by
node number; one DependencyTest expectation is updated accordingly.
Linear migration histories are unaffected (their topological order is
unique).

The non-linear stress test runs marginally faster than the previous
implementation (46 migrations: 2.3ms; 2002 migrations: 7.4s vs 9.8s).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ocharles ocharles changed the title Rewrite dependency resolution on algebraic-graphs (fixes exponential non-linear DAG slowdown) Rewrite dependency resolution on algebraic-graphs Jul 15, 2026
@ocharles ocharles changed the title Rewrite dependency resolution on algebraic-graphs Rewrite dependency resolution using algebraic-graphs Jul 15, 2026
@ocharles ocharles changed the title Rewrite dependency resolution using algebraic-graphs Rewrite dependency resolution using algebraic-graphs Jul 15, 2026
@ocharles
ocharles merged commit 460b545 into master Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant