Skip to content

Commit 9aaa5b5

Browse files
committed
Flatten the MergedIterator used to iterate over RangeQueryTree
Previously iterating over RangeQueryTree created a deep recursive tree of MergedIterators with RangeIterators actually delivering data at the leaves, causing a great deal of function call overhead. Instead, when creating the iterator, flatten the tree into a List of RangeIterators.
1 parent 0852d35 commit 9aaa5b5

File tree

1 file changed

+20
-12
lines changed

1 file changed

+20
-12
lines changed

src/projections/Tools/Timeline/RangeQueries/RangeQueryTree.java

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.Collection;
55
import java.util.Collections;
66
import java.util.Iterator;
7+
import java.util.List;
78

89
/** Provides a collection interface that provides efficient range queries via iterators.
910
* Does not allow insertion of null objects.
@@ -232,24 +233,31 @@ public Iterator<T> iterator() {
232233
return iterator(Long.MIN_VALUE, Long.MAX_VALUE);
233234
}
234235

235-
public Iterator iterator(long lb, long ub) {
236-
// System.out.println("Creating iterator for node " + nodeID + " data=" + data);
236+
public Iterator<T> iterator(long lb, long ub) {
237+
ArrayList<Iterator<T>> accumulator = new ArrayList<>();
238+
iteratorHelper(lb, ub, accumulator);
239+
240+
if(accumulator.isEmpty())
241+
accumulator.add(new NullIterator<>());
242+
243+
// Copying to a zero length array is a bit faster since the JVM avoids zeroing the array
244+
// (see https://shipilev.net/blog/2016/arrays-wisdom-ancients/ for more detail)
245+
return new MergedIterator<T>(accumulator.toArray(new Iterator[0]));
246+
}
247+
248+
// Recursively create a flat tree of iterators in accumulator by walking the range query tree
249+
private void iteratorHelper(long lb, long ub, List<Iterator<T>> accumulator) {
237250
if(data == null){
238251
boolean useLeft = leftChild.lowerBound <= ub && leftChild.upperBound >= lb;
239252
boolean useRight = rightChild.lowerBound <= ub && rightChild.upperBound >= lb;
240253

241-
if(useLeft && useRight)
242-
return new MergedIterator(leftChild.iterator(lb, ub), rightChild.iterator(lb, ub));
243-
else if(useLeft)
244-
return leftChild.iterator(lb, ub);
245-
else if(useRight)
246-
return rightChild.iterator(lb, ub);
247-
else
248-
return new NullIterator();
249-
254+
if(useLeft)
255+
leftChild.iteratorHelper(lb, ub, accumulator);
256+
if(useRight)
257+
rightChild.iteratorHelper(lb, ub, accumulator);
250258
} else {
251259
// A local range iterator:
252-
return new RangeIterator(data.iterator(), lb, ub);
260+
accumulator.add(new RangeIterator(data.iterator(), lb, ub));
253261
}
254262
}
255263

0 commit comments

Comments
 (0)