diff --git a/CMakeLists.txt b/CMakeLists.txt index 736268cd1..04cbf63ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,7 +98,7 @@ add_executable(datastructure-tests EXCLUDE_FROM_ALL UnitTests/datastructure_test add_executable(algorithm-tests EXCLUDE_FROM_ALL UnitTests/algorithm_tests.cpp ${AlgorithmTestsGlob} $ $ $) # Benchmarks -add_executable(rtree-bench EXCLUDE_FROM_ALL Benchmarks/static_rtree.cpp $ $ $) +add_executable(rtree-bench EXCLUDE_FROM_ALL benchmarks/static_rtree.cpp $ $ $) # Check the release mode if(NOT CMAKE_BUILD_TYPE MATCHES Debug) diff --git a/benchmarks/static_rtree.cpp b/benchmarks/static_rtree.cpp new file mode 100644 index 000000000..72ba3f2ef --- /dev/null +++ b/benchmarks/static_rtree.cpp @@ -0,0 +1,189 @@ +/* + +Copyright (c) 2014, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "../DataStructures/OriginalEdgeData.h" +#include "../DataStructures/QueryNode.h" +#include "../DataStructures/SharedMemoryVectorWrapper.h" +#include "../DataStructures/StaticRTree.h" +#include "../Util/BoostFileSystemFix.h" +#include "../DataStructures/EdgeBasedNode.h" + +#include + +#include + +// Choosen by a fair W20 dice roll (this value is completely arbitrary) +constexpr unsigned RANDOM_SEED = 13; +constexpr int32_t WORLD_MIN_LAT = -90 * COORDINATE_PRECISION; +constexpr int32_t WORLD_MAX_LAT = 90 * COORDINATE_PRECISION; +constexpr int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION; +constexpr int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION; + +using RTreeLeaf = EdgeBasedNode; +using FixedPointCoordinateListPtr = std::shared_ptr>; +using BenchStaticRTree = StaticRTree::vector, false>; + +FixedPointCoordinateListPtr LoadCoordinates(const boost::filesystem::path &nodes_file) +{ + boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary); + + QueryNode current_node; + unsigned number_of_coordinates = 0; + nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned)); + auto coords = std::make_shared>(number_of_coordinates); + for (unsigned i = 0; i < number_of_coordinates; ++i) + { + nodes_input_stream.read((char *)¤t_node, sizeof(QueryNode)); + coords->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon); + BOOST_ASSERT((std::abs(coords->at(i).lat) >> 30) == 0); + BOOST_ASSERT((std::abs(coords->at(i).lon) >> 30) == 0); + } + nodes_input_stream.close(); + return coords; +} + +void Benchmark(BenchStaticRTree &rtree, unsigned num_queries) +{ + std::mt19937 mt_rand(RANDOM_SEED); + std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT); + std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON); + std::vector queries; + for (unsigned i = 0; i < num_queries; i++) + { + queries.emplace_back(FixedPointCoordinate(lat_udist(mt_rand), lon_udist(mt_rand))); + } + + { + const unsigned num_results = 5; + std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results + << " phantom nodes" + << "\n"; + + TIMER_START(query_phantom); + std::vector resulting_phantom_node_vector; + for (const auto &q : queries) + { + resulting_phantom_node_vector.clear(); + rtree.IncrementalFindPhantomNodeForCoordinate( + q, resulting_phantom_node_vector, 3, num_results); + resulting_phantom_node_vector.clear(); + rtree.IncrementalFindPhantomNodeForCoordinate( + q, resulting_phantom_node_vector, 17, num_results); + } + TIMER_STOP(query_phantom); + + std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries + << " queries." + << "\n"; + std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query." + << "\n"; + + std::cout << "#### LocateClosestEndPointForCoordinate" + << "\n"; + } + + TIMER_START(query_endpoint); + FixedPointCoordinate result; + for (const auto &q : queries) + { + rtree.LocateClosestEndPointForCoordinate(q, result, 3); + } + TIMER_STOP(query_endpoint); + + std::cout << "Took " << TIMER_MSEC(query_endpoint) << " msec for " << num_queries << " queries." + << "\n"; + std::cout << TIMER_MSEC(query_endpoint) / ((double)num_queries) << " msec/query." + << "\n"; + + std::cout << "#### FindPhantomNodeForCoordinate" + << "\n"; + + TIMER_START(query_phantomnode); + for (const auto &q : queries) + { + PhantomNode phantom; + rtree.FindPhantomNodeForCoordinate(q, phantom, 3); + } + TIMER_STOP(query_phantomnode); + + std::cout << "Took " << TIMER_MSEC(query_phantomnode) << " msec for " << num_queries + << " queries." + << "\n"; + std::cout << TIMER_MSEC(query_phantomnode) / ((double)num_queries) << " msec/query." + << "\n"; + + { + const unsigned num_results = 1; + std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results + << " phantom nodes" + << "\n"; + + TIMER_START(query_phantom); + std::vector resulting_phantom_node_vector; + for (const auto &q : queries) + { + resulting_phantom_node_vector.clear(); + rtree.IncrementalFindPhantomNodeForCoordinate( + q, resulting_phantom_node_vector, 3, num_results); + resulting_phantom_node_vector.clear(); + rtree.IncrementalFindPhantomNodeForCoordinate( + q, resulting_phantom_node_vector, 17, num_results); + } + TIMER_STOP(query_phantom); + + std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries + << " queries." + << "\n"; + std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query." + << "\n"; + + std::cout << "#### LocateClosestEndPointForCoordinate" + << "\n"; + } +} + +int main(int argc, char **argv) +{ + if (argc < 4) + { + std::cout << "./rtree-bench file.ramIndex file.fileIndx file.nodes" + << "\n"; + return 1; + } + + const char *ramPath = argv[1]; + const char *filePath = argv[2]; + const char *nodesPath = argv[3]; + + auto coords = LoadCoordinates(nodesPath); + + BenchStaticRTree rtree(ramPath, filePath, coords); + + Benchmark(rtree, 10000); + + return 0; +}