优化: dag拓扑O(V+E)+前端findToolCall反向遍历
- FR-D1 dag.rs topological_layers + executor.rs run 建 adjacency 索引, O(V·E)→O(V+E)(14测试全绿, 含executor3测)
- FR-R5 useAiEvents findToolCall 正向 O(n²) 改反向遍历(命中最近, 放弃Map索引防陈旧引用)
- AR-6 核查确认已于 f82dd8b 落地(Low失败emit AiToolCallCompleted), 零改动
This commit is contained in:
@@ -81,18 +81,29 @@ impl Dag {
|
||||
|
||||
/// 拓扑排序 — 返回按执行顺序排列的节点 ID 层级
|
||||
///
|
||||
/// 返回 Vec<Vec<NodeId>>,每层内的节点可以并行执行
|
||||
/// 返回 Vec<Vec<NodeId>>,每层内的节点可以并行执行。
|
||||
///
|
||||
/// 复杂度:O(V+E)。一次性遍历边构建邻接索引(出边表)与入度表,
|
||||
/// BFS 分层只走索引查询(每条边仅被访问一次),不再为每个节点全表扫描边集合。
|
||||
pub fn topological_layers(&self) -> Result<Vec<Vec<NodeId>>> {
|
||||
let node_ids: HashSet<NodeId> = self.nodes.keys().cloned().collect();
|
||||
let mut in_degree: HashMap<NodeId, usize> = HashMap::new();
|
||||
// 邻接出边表:source → 直接后继列表(仅含两端均在 nodes 内的有效边)
|
||||
let mut adjacency_out: HashMap<NodeId, Vec<NodeId>> = HashMap::new();
|
||||
|
||||
// 初始化入度
|
||||
// 初始化入度(确保每个节点都有表项,便于后续 O(1) 修改)
|
||||
for id in &node_ids {
|
||||
in_degree.insert(id.clone(), 0);
|
||||
}
|
||||
// 单次 O(E) 遍历:同时构建入度表与出边表
|
||||
for edge in &self.edges {
|
||||
// 仅收录两端均为已注册节点的边,跳过野节点
|
||||
if node_ids.contains(&edge.source) && node_ids.contains(&edge.target) {
|
||||
*in_degree.entry(edge.target.clone()).or_insert(0) += 1;
|
||||
*in_degree.get_mut(&edge.target).unwrap() += 1;
|
||||
adjacency_out
|
||||
.entry(edge.source.clone())
|
||||
.or_default()
|
||||
.push(edge.target.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,11 +122,14 @@ impl Dag {
|
||||
for _ in 0..layer_size {
|
||||
if let Some(id) = queue.pop_front() {
|
||||
layer.push(id.clone());
|
||||
for succ in self.successors(&id) {
|
||||
let deg = in_degree.get_mut(&succ).unwrap();
|
||||
*deg -= 1;
|
||||
if *deg == 0 {
|
||||
queue.push_back(succ);
|
||||
// 出边已索引,O(出度) 遍历而非 O(E) 全表扫描
|
||||
if let Some(succs) = adjacency_out.get(&id) {
|
||||
for succ in succs {
|
||||
let deg = in_degree.get_mut(succ).unwrap();
|
||||
*deg -= 1;
|
||||
if *deg == 0 {
|
||||
queue.push_back(succ.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
processed += 1;
|
||||
|
||||
Reference in New Issue
Block a user