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