Re-use priority queue in StaticRTree (#6952)
This commit is contained in:
parent
5a48ce85b3
commit
0e17869e21
@ -24,6 +24,7 @@
|
|||||||
- NodeJS:
|
- NodeJS:
|
||||||
- CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452)
|
- CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452)
|
||||||
- Misc:
|
- Misc:
|
||||||
|
- CHANGED: Re-use priority queue in StaticRTree. [#6952](https://github.com/Project-OSRM/osrm-backend/pull/6952)
|
||||||
- CHANGED: Optimise encodePolyline function. [#6940](https://github.com/Project-OSRM/osrm-backend/pull/6940)
|
- CHANGED: Optimise encodePolyline function. [#6940](https://github.com/Project-OSRM/osrm-backend/pull/6940)
|
||||||
- CHANGED: Avoid reallocations in base64 encoding. [#6951](https://github.com/Project-OSRM/osrm-backend/pull/6951)
|
- CHANGED: Avoid reallocations in base64 encoding. [#6951](https://github.com/Project-OSRM/osrm-backend/pull/6951)
|
||||||
- CHANGED: Get rid of unused Boost dependencies. [#6960](https://github.com/Project-OSRM/osrm-backend/pull/6960)
|
- CHANGED: Get rid of unused Boost dependencies. [#6960](https://github.com/Project-OSRM/osrm-backend/pull/6960)
|
||||||
|
40
include/util/binary_heap.hpp
Normal file
40
include/util/binary_heap.hpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <algorithm>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace osrm::util
|
||||||
|
{
|
||||||
|
|
||||||
|
// in its essence it is std::priority_queue, but with `clear` method
|
||||||
|
template <typename T> class BinaryHeap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool empty() const { return heap_.empty(); }
|
||||||
|
|
||||||
|
const T &top() const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(!heap_.empty());
|
||||||
|
return heap_.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop()
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(!heap_.empty());
|
||||||
|
std::pop_heap(heap_.begin(), heap_.end());
|
||||||
|
heap_.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args> void emplace(Args &&...args)
|
||||||
|
{
|
||||||
|
heap_.emplace_back(std::forward<Args>(args)...);
|
||||||
|
std::push_heap(heap_.begin(), heap_.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() { heap_.clear(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<T> heap_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace osrm::util
|
@ -2,7 +2,9 @@
|
|||||||
#define STATIC_RTREE_HPP
|
#define STATIC_RTREE_HPP
|
||||||
|
|
||||||
#include "storage/tar_fwd.hpp"
|
#include "storage/tar_fwd.hpp"
|
||||||
|
#include "osrm/coordinate.hpp"
|
||||||
#include "util/bearing.hpp"
|
#include "util/bearing.hpp"
|
||||||
|
#include "util/binary_heap.hpp"
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
#include "util/deallocating_vector.hpp"
|
#include "util/deallocating_vector.hpp"
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
@ -15,8 +17,6 @@
|
|||||||
#include "util/vector_view.hpp"
|
#include "util/vector_view.hpp"
|
||||||
#include "util/web_mercator.hpp"
|
#include "util/web_mercator.hpp"
|
||||||
|
|
||||||
#include "osrm/coordinate.hpp"
|
|
||||||
|
|
||||||
#include "storage/shared_memory_ownership.hpp"
|
#include "storage/shared_memory_ownership.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
@ -554,9 +554,12 @@ class StaticRTree
|
|||||||
auto projected_coordinate = web_mercator::fromWGS84(input_coordinate);
|
auto projected_coordinate = web_mercator::fromWGS84(input_coordinate);
|
||||||
Coordinate fixed_projected_coordinate{projected_coordinate};
|
Coordinate fixed_projected_coordinate{projected_coordinate};
|
||||||
|
|
||||||
|
// we re-use queue for each query to avoid re-allocating memory
|
||||||
|
static thread_local util::BinaryHeap<QueryCandidate> traversal_queue;
|
||||||
|
|
||||||
|
traversal_queue.clear();
|
||||||
// initialize queue with root element
|
// initialize queue with root element
|
||||||
std::priority_queue<QueryCandidate> traversal_queue;
|
traversal_queue.emplace(QueryCandidate{0, TreeIndex{}});
|
||||||
traversal_queue.push(QueryCandidate{0, TreeIndex{}});
|
|
||||||
|
|
||||||
while (!traversal_queue.empty())
|
while (!traversal_queue.empty())
|
||||||
{
|
{
|
||||||
@ -710,7 +713,8 @@ class StaticRTree
|
|||||||
// distance must be non-negative
|
// distance must be non-negative
|
||||||
BOOST_ASSERT(0. <= squared_distance);
|
BOOST_ASSERT(0. <= squared_distance);
|
||||||
BOOST_ASSERT(i < std::numeric_limits<std::uint32_t>::max());
|
BOOST_ASSERT(i < std::numeric_limits<std::uint32_t>::max());
|
||||||
traversal_queue.push(QueryCandidate{squared_distance,
|
|
||||||
|
traversal_queue.emplace(QueryCandidate{squared_distance,
|
||||||
leaf_id,
|
leaf_id,
|
||||||
static_cast<std::uint32_t>(i),
|
static_cast<std::uint32_t>(i),
|
||||||
Coordinate{projected_nearest}});
|
Coordinate{projected_nearest}});
|
||||||
@ -742,7 +746,7 @@ class StaticRTree
|
|||||||
child.minimum_bounding_rectangle.GetMinSquaredDist(
|
child.minimum_bounding_rectangle.GetMinSquaredDist(
|
||||||
fixed_projected_input_coordinate);
|
fixed_projected_input_coordinate);
|
||||||
|
|
||||||
traversal_queue.push(QueryCandidate{
|
traversal_queue.emplace(QueryCandidate{
|
||||||
squared_lower_bound_to_element,
|
squared_lower_bound_to_element,
|
||||||
TreeIndex(parent.level + 1, child_index - m_tree_level_starts[parent.level + 1])});
|
TreeIndex(parent.level + 1, child_index - m_tree_level_starts[parent.level + 1])});
|
||||||
}
|
}
|
||||||
|
132
unit_tests/util/binary_heap.cpp
Normal file
132
unit_tests/util/binary_heap.cpp
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
#include "util/binary_heap.hpp"
|
||||||
|
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(binary_heap_test)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(empty_heap)
|
||||||
|
{
|
||||||
|
osrm::util::BinaryHeap<int> heap;
|
||||||
|
BOOST_CHECK(heap.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(push_and_top)
|
||||||
|
{
|
||||||
|
osrm::util::BinaryHeap<int> heap;
|
||||||
|
heap.emplace(5);
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), 5);
|
||||||
|
BOOST_CHECK(!heap.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(push_multiple_and_order)
|
||||||
|
{
|
||||||
|
osrm::util::BinaryHeap<int> heap;
|
||||||
|
heap.emplace(5);
|
||||||
|
heap.emplace(10);
|
||||||
|
heap.emplace(3);
|
||||||
|
heap.emplace(8);
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(pop_and_order)
|
||||||
|
{
|
||||||
|
osrm::util::BinaryHeap<int> heap;
|
||||||
|
heap.emplace(5);
|
||||||
|
heap.emplace(10);
|
||||||
|
heap.emplace(3);
|
||||||
|
heap.emplace(8);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), 10);
|
||||||
|
heap.pop();
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), 8);
|
||||||
|
heap.pop();
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), 5);
|
||||||
|
heap.pop();
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), 3);
|
||||||
|
heap.pop();
|
||||||
|
BOOST_CHECK(heap.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(clear_heap)
|
||||||
|
{
|
||||||
|
osrm::util::BinaryHeap<int> heap;
|
||||||
|
heap.emplace(5);
|
||||||
|
heap.emplace(10);
|
||||||
|
heap.clear();
|
||||||
|
BOOST_CHECK(heap.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(emplace_with_custom_type)
|
||||||
|
{
|
||||||
|
struct CustomType
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
CustomType(int v) : value(v) {}
|
||||||
|
bool operator<(const CustomType &other) const { return value < other.value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
osrm::util::BinaryHeap<CustomType> heap;
|
||||||
|
heap.emplace(5);
|
||||||
|
heap.emplace(10);
|
||||||
|
heap.emplace(3);
|
||||||
|
BOOST_CHECK_EQUAL(heap.top().value, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(large_number_of_elements)
|
||||||
|
{
|
||||||
|
osrm::util::BinaryHeap<int> heap;
|
||||||
|
for (int i = 0; i < 1000; ++i)
|
||||||
|
{
|
||||||
|
heap.emplace(i);
|
||||||
|
}
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), 999);
|
||||||
|
|
||||||
|
for (int i = 999; i >= 0; --i)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), i);
|
||||||
|
heap.pop();
|
||||||
|
}
|
||||||
|
BOOST_CHECK(heap.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(duplicate_values)
|
||||||
|
{
|
||||||
|
osrm::util::BinaryHeap<int> heap;
|
||||||
|
heap.emplace(5);
|
||||||
|
heap.emplace(5);
|
||||||
|
heap.emplace(5);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), 5);
|
||||||
|
heap.pop();
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), 5);
|
||||||
|
heap.pop();
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), 5);
|
||||||
|
heap.pop();
|
||||||
|
BOOST_CHECK(heap.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(string_type)
|
||||||
|
{
|
||||||
|
osrm::util::BinaryHeap<std::string> heap;
|
||||||
|
heap.emplace("apple");
|
||||||
|
heap.emplace("banana");
|
||||||
|
heap.emplace("cherry");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), "cherry");
|
||||||
|
heap.pop();
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), "banana");
|
||||||
|
heap.pop();
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), "apple");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(emplace_after_clear)
|
||||||
|
{
|
||||||
|
osrm::util::BinaryHeap<int> heap;
|
||||||
|
heap.emplace(5);
|
||||||
|
heap.clear();
|
||||||
|
heap.emplace(10);
|
||||||
|
BOOST_CHECK_EQUAL(heap.top(), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
Reference in New Issue
Block a user