Skip to content

Commit fc2e61e

Browse files
Kontinuationkylebarron
authored andcommitted
[EWT-2995] Optimize the performance of RTree search (#2)
* Optimize the performance of RTree search
1 parent 7bd95bd commit fc2e61e

File tree

1 file changed

+22
-16
lines changed

1 file changed

+22
-16
lines changed

src/rtree/trait.rs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::cmp::Reverse;
2-
use std::collections::BinaryHeap;
2+
use std::collections::{BinaryHeap, VecDeque};
3+
use std::vec;
34

45
use geo_traits::{CoordTrait, RectTrait};
56

@@ -80,7 +81,7 @@ pub trait RTreeIndex<N: IndexableNum>: Sized {
8081

8182
let mut outer_node_index = boxes.len().checked_sub(4);
8283

83-
let mut queue = vec![];
84+
let mut queue = VecDeque::with_capacity(self.node_size() as usize);
8485
let mut results = vec![];
8586

8687
while let Some(node_index) = outer_node_index {
@@ -90,31 +91,36 @@ pub trait RTreeIndex<N: IndexableNum>: Sized {
9091

9192
// search through child nodes
9293
for pos in (node_index..end).step_by(4) {
93-
// check if node bbox intersects with query bbox
94-
if max_x < boxes[pos] {
95-
continue; // maxX < nodeMinX
96-
}
97-
if max_y < boxes[pos + 1] {
98-
continue; // maxY < nodeMinY
99-
}
100-
if min_x > boxes[pos + 2] {
101-
continue; // minX > nodeMaxX
102-
}
103-
if min_y > boxes[pos + 3] {
104-
continue; // minY > nodeMaxY
94+
// Safety: pos was checked before to be within bounds
95+
// Justification: avoiding bounds check improves performance by up to 30%
96+
let (node_min_x, node_min_y, node_max_x, node_max_y) = unsafe {
97+
let node_min_x = *boxes.get_unchecked(pos);
98+
let node_min_y = *boxes.get_unchecked(pos + 1);
99+
let node_max_x = *boxes.get_unchecked(pos + 2);
100+
let node_max_y = *boxes.get_unchecked(pos + 3);
101+
(node_min_x, node_min_y, node_max_x, node_max_y)
102+
};
103+
104+
// check if the query box disjoint with the node box
105+
if max_x < node_min_x
106+
|| max_y < node_min_y
107+
|| min_x > node_max_x
108+
|| min_y > node_max_y
109+
{
110+
continue;
105111
}
106112

107113
let index = indices.get(pos >> 2);
108114

109115
if node_index >= self.num_items() as usize * 4 {
110-
queue.push(index); // node; add it to the search queue
116+
queue.push_back(index); // node; add it to the search queue
111117
} else {
112118
// Since the max items of the index is u32, we can coerce to u32
113119
results.push(index.try_into().unwrap()); // leaf item
114120
}
115121
}
116122

117-
outer_node_index = queue.pop();
123+
outer_node_index = queue.pop_front();
118124
}
119125

120126
results

0 commit comments

Comments
 (0)