Re-use priority queue in StaticRTree (#6952)
This commit is contained in:
		
							parent
							
								
									5a48ce85b3
								
							
						
					
					
						commit
						0e17869e21
					
				| @ -24,6 +24,7 @@ | ||||
|     - NodeJS: | ||||
|       - CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452) | ||||
|     - 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: 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) | ||||
|  | ||||
							
								
								
									
										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 | ||||
| 
 | ||||
| #include "storage/tar_fwd.hpp" | ||||
| #include "osrm/coordinate.hpp" | ||||
| #include "util/bearing.hpp" | ||||
| #include "util/binary_heap.hpp" | ||||
| #include "util/coordinate_calculation.hpp" | ||||
| #include "util/deallocating_vector.hpp" | ||||
| #include "util/exception.hpp" | ||||
| @ -15,8 +17,6 @@ | ||||
| #include "util/vector_view.hpp" | ||||
| #include "util/web_mercator.hpp" | ||||
| 
 | ||||
| #include "osrm/coordinate.hpp" | ||||
| 
 | ||||
| #include "storage/shared_memory_ownership.hpp" | ||||
| 
 | ||||
| #include <boost/assert.hpp> | ||||
| @ -554,9 +554,12 @@ class StaticRTree | ||||
|         auto projected_coordinate = web_mercator::fromWGS84(input_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
 | ||||
|         std::priority_queue<QueryCandidate> traversal_queue; | ||||
|         traversal_queue.push(QueryCandidate{0, TreeIndex{}}); | ||||
|         traversal_queue.emplace(QueryCandidate{0, TreeIndex{}}); | ||||
| 
 | ||||
|         while (!traversal_queue.empty()) | ||||
|         { | ||||
| @ -710,7 +713,8 @@ class StaticRTree | ||||
|             // distance must be non-negative
 | ||||
|             BOOST_ASSERT(0. <= squared_distance); | ||||
|             BOOST_ASSERT(i < std::numeric_limits<std::uint32_t>::max()); | ||||
|             traversal_queue.push(QueryCandidate{squared_distance, | ||||
| 
 | ||||
|             traversal_queue.emplace(QueryCandidate{squared_distance, | ||||
|                                                    leaf_id, | ||||
|                                                    static_cast<std::uint32_t>(i), | ||||
|                                                    Coordinate{projected_nearest}}); | ||||
| @ -742,7 +746,7 @@ class StaticRTree | ||||
|                 child.minimum_bounding_rectangle.GetMinSquaredDist( | ||||
|                     fixed_projected_input_coordinate); | ||||
| 
 | ||||
|             traversal_queue.push(QueryCandidate{ | ||||
|             traversal_queue.emplace(QueryCandidate{ | ||||
|                 squared_lower_bound_to_element, | ||||
|                 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