Fix bug in GraphOutputWriter#partitionedFactored which caused queue to grow to O(E), and now upper-bounding it to O(N).
RELNOTES: None.
PiperOrigin-RevId: 605164658
Change-Id: I3f0bb10ebc72d7aa2a8b36a331753db4b396927d
diff --git a/src/main/java/com/google/devtools/build/lib/query2/query/output/GraphOutputWriter.java b/src/main/java/com/google/devtools/build/lib/query2/query/output/GraphOutputWriter.java
index ca6fe2c..b75e67d 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/query/output/GraphOutputWriter.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/query/output/GraphOutputWriter.java
@@ -283,6 +283,7 @@
// already belongs to one.
HashMap<Node<T>, Set<Node<T>>> eqClasses = new HashMap<>();
ArrayDeque<Node<T>> queue = new ArrayDeque<>(graph.getRoots());
+ Set<Node<T>> enqueued = new HashSet<>(graph.getRoots());
// Top-level nodes need to be compared amongst each other because they can form an equivalence
// class amongst themselves too.
@@ -292,7 +293,13 @@
Node<T> node = queue.removeFirst();
List<Node<T>> successors = new ArrayList<>(node.getSuccessors());
processSuccessors(successors, eqClasses, equivalenceRelation);
- queue.addAll(node.getSuccessors());
+ for (Node<T> child : node.getSuccessors()) {
+ // We don't want the queue to grow to O(E); also, there is no need to visit children twice.
+ if (!enqueued.contains(child)) {
+ queue.add(child);
+ enqueued.add(child);
+ }
+ }
}
return eqClasses.values().stream().distinct().collect(toImmutableList());