From 6c1c21fadf09cfe088817b03d8eb646f9685bb2a Mon Sep 17 00:00:00 2001 From: xiaowei Date: Sun, 6 Sep 2026 01:20:21 +0800 Subject: [PATCH] =?UTF-8?q?perf(pagerank):=20O(V+E)=20=E7=B4=AF=E5=8A=A0?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=9B=BF=E4=BB=A3=20O(V=C2=B2)=20=E5=85=A8?= =?UTF-8?q?=E6=BA=90=E9=81=8D=E5=8E=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 旧实现每目标节点遍历全部源节点找边匹配 (943-961): - 17628 nodes × 20 迭代 = 6.2亿次内层操作 → 单次 PageRank ~3 分钟 - 重启后多套触发器零值连锁 fire full consolidation → CPU 100% 持续 10+ 分钟 新实现先归一化每源节点总权重, 再沿出边把贡献累加到目标 (O(V+E)): - 17628 nodes PageRank + 图谱维护: 3分钟 → <1 秒 - 重启风暴从 10+ 分钟 CPU 100% → 秒级无感 实测: 01:16:40 图谱维护开始 → 01:16:41 PageRank 更新 17628 nodes 完成 --- go/internal/governance/graph_sqlite.go | 33 +++++++++++++++----------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/go/internal/governance/graph_sqlite.go b/go/internal/governance/graph_sqlite.go index f667710..4d44609 100644 --- a/go/internal/governance/graph_sqlite.go +++ b/go/internal/governance/graph_sqlite.go @@ -941,21 +941,26 @@ func (gs *SQLiteGraphStore) PageRank(damping float64, iterations int) map[string } for iter := 0; iter < iterations; iter++ { - newRanks := make(map[string]float64) - for _, node := range nodes { - rank := base - for src, edges := range outEdges { - totalWt := 0.0 - for _, e := range edges { - totalWt += e.weight - } - for _, e := range edges { - if e.target == node && totalWt > 0 { - rank += damping * ranks[src] * e.weight / totalWt - } - } + // 正确 PageRank 实现 O(V+E):先归一化每个源节点总权重, + // 再沿出边把贡献直接累加到目标节点(旧实现每目标遍历全源 O(V²), + // 17628 节点 × 20 迭代 = 6.2 亿次 → 3 分钟;现在亚秒级) + contrib := make(map[string]float64, len(outEdges)) + for src, edges := range outEdges { + totalWt := 0.0 + for _, e := range edges { + totalWt += e.weight } - newRanks[node] = rank + if totalWt <= 0 { + continue + } + share := damping * ranks[src] / totalWt + for _, e := range edges { + contrib[e.target] += share * e.weight + } + } + newRanks := make(map[string]float64, len(nodes)) + for _, node := range nodes { + newRanks[node] = base + contrib[node] } ranks = newRanks }