Found while recording XYG's GraphForge composition scale evidence (CurateLabs/xyg#930). In @curatelabs/graphforge 0.5.2, analyze("minimum_spanning_tree", ...) grows much faster than linear on a sparse graph, while the other algorithms on the same graph stay near-linear.
| nodes (edges) |
pagerank |
louvain |
minimum_spanning_tree |
dijkstra |
| 1,000 (2,000) |
5.6 ms |
7.8 ms |
97 ms |
3.7 ms |
| 10,000 (20,000) |
46 ms |
94 ms |
4,140 ms |
27 ms |
| 100,000 (200,000) |
783 ms |
2,195 ms |
468,618 ms |
744 ms |
Each 10× step costs about 43× then 113×, which looks closer to O(V·E) or O(V²) than Kruskal/Prim's O(E log V). #582 (closed) polished MST scale earlier, so this may be a regression or a path #582 didn't cover (weighted, directed=false).
Setup
- Graph: two weighted edges per node, a seeded small-world pattern (
i → i+1 and i → i+k), loaded through bulk construction contract v1 (publishBulkNodes/publishBulkEdges, UUIDv7 ids).
- Inputs:
CurateLabs/xyg benchmarks/gen_graphforge_scale_inputs.py --out DIR --sizes 1000,10000,100000.
- Call:
g.analyze("minimum_spanning_tree", "Person", null, false, "w").
- Machine: linux-x64, Node 22.22.1, AMD Ryzen 7 3800X (16 threads), timed in-process.
Repro
const { GraphForge } = require("@curatelabs/graphforge");
const g = new GraphForge();
g.publishBulkNodes(uuidv7(), fs.readFileSync("nodes-100000.arrow"));
g.publishBulkEdges(uuidv7(), fs.readFileSync("edges-100000.arrow"));
console.time("mst");
g.analyze("minimum_spanning_tree", "Person", null, false, "w");
console.timeEnd("mst");
Raw numbers: spec/benchmarks/graphforge-compose-local.json in CurateLabs/xyg#930 (graphforge.timings_ms).
Found while recording XYG's GraphForge composition scale evidence (CurateLabs/xyg#930). In
@curatelabs/graphforge0.5.2,analyze("minimum_spanning_tree", ...)grows much faster than linear on a sparse graph, while the other algorithms on the same graph stay near-linear.Each 10× step costs about 43× then 113×, which looks closer to O(V·E) or O(V²) than Kruskal/Prim's O(E log V). #582 (closed) polished MST scale earlier, so this may be a regression or a path #582 didn't cover (weighted,
directed=false).Setup
i → i+1andi → i+k), loaded through bulk construction contract v1 (publishBulkNodes/publishBulkEdges, UUIDv7 ids).CurateLabs/xygbenchmarks/gen_graphforge_scale_inputs.py --out DIR --sizes 1000,10000,100000.g.analyze("minimum_spanning_tree", "Person", null, false, "w").Repro
Raw numbers:
spec/benchmarks/graphforge-compose-local.jsonin CurateLabs/xyg#930 (graphforge.timings_ms).