mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 04:51:51 +00:00
perf(attack-paths): optimize getPathEdges with O(1) adjacency maps
Pre-build parent and children maps at the start of traversal for O(1) lookups instead of O(n) array searches per traversal step. This improves performance for large attack path graphs.
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
* Upstream: follows only ONE parent path (first parent at each level) to avoid lighting up siblings
|
||||
* Downstream: follows ALL children recursively
|
||||
*
|
||||
* Uses pre-built adjacency maps for O(1) lookups instead of O(n) array searches per traversal step.
|
||||
*
|
||||
* @param nodeId - The starting node ID
|
||||
* @param edges - Array of edges with sourceId and targetId
|
||||
* @returns Set of edge IDs in the format "sourceId-targetId"
|
||||
@@ -15,6 +17,23 @@ export const getPathEdges = (
|
||||
nodeId: string,
|
||||
edges: Array<{ sourceId: string; targetId: string }>,
|
||||
): Set<string> => {
|
||||
// Build adjacency maps once - O(n)
|
||||
const parentMap = new Map<string, { sourceId: string; targetId: string }>();
|
||||
const childrenMap = new Map<
|
||||
string,
|
||||
Array<{ sourceId: string; targetId: string }>
|
||||
>();
|
||||
|
||||
edges.forEach((edge) => {
|
||||
// First parent only (matches original behavior of find())
|
||||
if (!parentMap.has(edge.targetId)) {
|
||||
parentMap.set(edge.targetId, edge);
|
||||
}
|
||||
const children = childrenMap.get(edge.sourceId) || [];
|
||||
children.push(edge);
|
||||
childrenMap.set(edge.sourceId, children);
|
||||
});
|
||||
|
||||
const pathEdgeIds = new Set<string>();
|
||||
const visitedNodes = new Set<string>();
|
||||
|
||||
@@ -24,8 +43,7 @@ export const getPathEdges = (
|
||||
if (visitedNodes.has(`up-${currentNodeId}`)) return;
|
||||
visitedNodes.add(`up-${currentNodeId}`);
|
||||
|
||||
// Find the first parent edge only
|
||||
const parentEdge = edges.find((edge) => edge.targetId === currentNodeId);
|
||||
const parentEdge = parentMap.get(currentNodeId); // O(1) lookup
|
||||
if (parentEdge) {
|
||||
pathEdgeIds.add(`${parentEdge.sourceId}-${parentEdge.targetId}`);
|
||||
traverseUpstream(parentEdge.sourceId);
|
||||
@@ -37,11 +55,10 @@ export const getPathEdges = (
|
||||
if (visitedNodes.has(`down-${currentNodeId}`)) return;
|
||||
visitedNodes.add(`down-${currentNodeId}`);
|
||||
|
||||
edges.forEach((edge) => {
|
||||
if (edge.sourceId === currentNodeId) {
|
||||
pathEdgeIds.add(`${edge.sourceId}-${edge.targetId}`);
|
||||
traverseDownstream(edge.targetId);
|
||||
}
|
||||
const children = childrenMap.get(currentNodeId) || []; // O(1) lookup
|
||||
children.forEach((edge) => {
|
||||
pathEdgeIds.add(`${edge.sourceId}-${edge.targetId}`);
|
||||
traverseDownstream(edge.targetId);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user