Add cache for CandidateSegments to reduce heap worke even more

This commit is contained in:
Patrick Niklaus 2016-04-30 04:19:03 +02:00
parent 7357a8d42b
commit 9692be6f50
No known key found for this signature in database
GPG Key ID: E426891B5F978B1B

View File

@ -43,7 +43,8 @@ template <class EdgeDataT,
class CoordinateListT = std::vector<Coordinate>, class CoordinateListT = std::vector<Coordinate>,
bool UseSharedMemory = false, bool UseSharedMemory = false,
std::uint32_t BRANCHING_FACTOR = 64, std::uint32_t BRANCHING_FACTOR = 64,
std::uint32_t LEAF_NODE_SIZE = 256> std::uint32_t LEAF_NODE_SIZE = 256,
std::uint32_t MAX_NUM_CANDIDATES = LEAF_NODE_SIZE * 10>
class StaticRTree class StaticRTree
{ {
public: public:
@ -93,7 +94,9 @@ class StaticRTree
} }
}; };
using QueryNodeType = mapbox::util::variant<std::uint32_t, CandidateSegment>; struct TreeIndex { std::uint32_t index; };
struct SegmentIndex { std::uint32_t index; };
using QueryNodeType = mapbox::util::variant<TreeIndex, SegmentIndex>;
struct QueryCandidate struct QueryCandidate
{ {
inline bool operator<(const QueryCandidate &other) const inline bool operator<(const QueryCandidate &other) const
@ -415,21 +418,26 @@ class StaticRTree
// initialize queue with root element // initialize queue with root element
std::priority_queue<QueryCandidate> traversal_queue; std::priority_queue<QueryCandidate> traversal_queue;
traversal_queue.push(QueryCandidate{0, 0}); traversal_queue.push(QueryCandidate{0, TreeIndex{0}});
// we need to limit the size of this vector to MAX_NUM_CANDIDATES
// otherwise this could fill up
std::vector<CandidateSegment> candidate_cache;
candidate_cache.reserve(LEAF_NODE_SIZE);
while (!traversal_queue.empty()) while (!traversal_queue.empty())
{ {
QueryCandidate current_query_node = traversal_queue.top(); QueryCandidate current_query_node = traversal_queue.top();
traversal_queue.pop(); traversal_queue.pop();
if (current_query_node.node.template is<std::uint32_t>()) if (current_query_node.node.template is<TreeIndex>())
{ // current object is a tree node { // current object is a tree node
const TreeNode &current_tree_node = const TreeNode &current_tree_node =
m_search_tree[current_query_node.node.template get<std::uint32_t>()]; m_search_tree[current_query_node.node.template get<TreeIndex>().index];
if (current_tree_node.child_is_on_disk) if (current_tree_node.child_is_on_disk)
{ {
ExploreLeafNode(current_tree_node.children[0], fixed_projected_coordinate, ExploreLeafNode(current_tree_node.children[0], fixed_projected_coordinate,
projected_coordinate, traversal_queue); projected_coordinate, traversal_queue, candidate_cache);
} }
else else
{ {
@ -439,7 +447,7 @@ class StaticRTree
else else
{ {
// inspecting an actual road segment // inspecting an actual road segment
auto &current_candidate = current_query_node.node.template get<CandidateSegment>(); auto &current_candidate = candidate_cache[current_query_node.node.template get<SegmentIndex>().index];
// to allow returns of no-results if too restrictive filtering, this needs to be done here // to allow returns of no-results if too restrictive filtering, this needs to be done here
// even though performance would indicate that we want to stop after adding the first candidate // even though performance would indicate that we want to stop after adding the first candidate
@ -470,8 +478,16 @@ class StaticRTree
void ExploreLeafNode(const std::uint32_t leaf_id, void ExploreLeafNode(const std::uint32_t leaf_id,
const Coordinate projected_input_coordinate_fixed, const Coordinate projected_input_coordinate_fixed,
const FloatCoordinate &projected_input_coordinate, const FloatCoordinate &projected_input_coordinate,
QueueT &traversal_queue) QueueT &traversal_queue,
std::vector<CandidateSegment> &candidate_cache)
{ {
// we are not going to load any more elements, because the cache would
// fill up
if (candidate_cache.size() > MAX_NUM_CANDIDATES)
{
return;
}
LeafNode current_leaf_node; LeafNode current_leaf_node;
LoadLeafFromDisk(leaf_id, current_leaf_node); LoadLeafFromDisk(leaf_id, current_leaf_node);
@ -491,9 +507,8 @@ class StaticRTree
projected_input_coordinate_fixed, projected_nearest); projected_input_coordinate_fixed, projected_nearest);
// distance must be non-negative // distance must be non-negative
BOOST_ASSERT(0. <= squared_distance); BOOST_ASSERT(0. <= squared_distance);
traversal_queue.push( traversal_queue.push(QueryCandidate{squared_distance, SegmentIndex {static_cast<std::uint32_t>(candidate_cache.size())}});
QueryCandidate{squared_distance, CandidateSegment{Coordinate{projected_nearest}, candidate_cache.push_back(CandidateSegment{Coordinate{projected_nearest}, std::move(current_edge)});
std::move(current_edge)}});
} }
} }
@ -510,7 +525,7 @@ class StaticRTree
const auto squared_lower_bound_to_element = const auto squared_lower_bound_to_element =
child_rectangle.GetMinSquaredDist(fixed_projected_input_coordinate); child_rectangle.GetMinSquaredDist(fixed_projected_input_coordinate);
traversal_queue.push( traversal_queue.push(
QueryCandidate{squared_lower_bound_to_element, child_id}); QueryCandidate{squared_lower_bound_to_element, TreeIndex{static_cast<std::uint32_t>(child_id)}});
} }
} }