benchmark_experimental.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. // Boost.Geometry Index
  2. // Additional tests
  3. // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
  4. // Use, modification and distribution is subject to the Boost Software License,
  5. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #define BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
  8. #include <iostream>
  9. #include <boost/chrono.hpp>
  10. #include <boost/foreach.hpp>
  11. #include <boost/random.hpp>
  12. #include <boost/range/algorithm/copy.hpp>
  13. #include <boost/geometry.hpp>
  14. #include <boost/geometry/index/rtree.hpp>
  15. #include <boost/geometry/geometries/linestring.hpp>
  16. #include <boost/geometry/geometries/segment.hpp>
  17. #include <boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp>
  18. #include <boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp>
  19. namespace bg = boost::geometry;
  20. namespace bgi = bg::index;
  21. typedef bg::model::point<double, 2, bg::cs::cartesian> P;
  22. typedef bg::model::box<P> B;
  23. typedef bg::model::linestring<P> LS;
  24. typedef bg::model::segment<P> S;
  25. //typedef P V;
  26. typedef B V;
  27. //typedef S V;
  28. //#define SEGMENT_INDEXABLE
  29. template <typename V>
  30. struct generate_value {};
  31. template <>
  32. struct generate_value<B>
  33. {
  34. static inline B apply(float x, float y) { return B(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f)); }
  35. };
  36. template <>
  37. struct generate_value<S>
  38. {
  39. static inline S apply(float x, float y) { return S(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f)); }
  40. };
  41. template <>
  42. struct generate_value<P>
  43. {
  44. static inline P apply(float x, float y) { return P(x, y); }
  45. };
  46. //#include <boost/geometry/extensions/nsphere/nsphere.hpp>
  47. //typedef bg::model::nsphere<P, double> NS;
  48. //typedef NS V;
  49. //
  50. //template <>
  51. //struct generate_value<NS>
  52. //{
  53. // static inline NS apply(float x, float y) { return NS(P(x, y), 0.5); }
  54. //};
  55. template <typename I1, typename I2, typename O>
  56. void mycopy(I1 first, I2 last, O o)
  57. {
  58. for ( ; first != last ; ++o, ++first )
  59. *o = *first;
  60. }
  61. //#define BOOST_GEOMETRY_INDEX_BENCHMARK_DEBUG
  62. int main()
  63. {
  64. typedef boost::chrono::thread_clock clock_t;
  65. typedef boost::chrono::duration<float> dur_t;
  66. #ifndef BOOST_GEOMETRY_INDEX_BENCHMARK_DEBUG
  67. size_t values_count = 1000000;
  68. size_t queries_count = 100000;
  69. size_t nearest_queries_count = 20000;
  70. unsigned neighbours_count = 10;
  71. size_t path_queries_count = 2000;
  72. size_t path_queries_count2 = 20000;
  73. unsigned path_values_count = 10;
  74. #else
  75. size_t values_count = 1000;
  76. size_t queries_count = 1;
  77. size_t nearest_queries_count = 1;
  78. unsigned neighbours_count = 10;
  79. size_t path_queries_count = 1;
  80. size_t path_queries_count2 = 1;
  81. unsigned path_values_count = 10;
  82. #endif
  83. float max_val = static_cast<float>(values_count / 2);
  84. std::vector< std::pair<float, float> > coords;
  85. std::vector<V> values;
  86. //randomize values
  87. {
  88. boost::mt19937 rng;
  89. //rng.seed(static_cast<unsigned int>(std::time(0)));
  90. boost::uniform_real<float> range(-max_val, max_val);
  91. boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > rnd(rng, range);
  92. coords.reserve(values_count);
  93. std::cout << "randomizing data\n";
  94. for ( size_t i = 0 ; i < values_count ; ++i )
  95. {
  96. float x = rnd();
  97. float y = rnd();
  98. coords.push_back(std::make_pair(x, y));
  99. values.push_back(generate_value<V>::apply(x, y));
  100. }
  101. std::cout << "randomized\n";
  102. }
  103. typedef bgi::rtree<V, bgi::linear<16, 4> > RT;
  104. //typedef bgi::rtree<V, bgi::quadratic<16, 4> > RT;
  105. //typedef bgi::rtree<V, bgi::rstar<16, 4> > RT;
  106. std::cout << "sizeof rtree: " << sizeof(RT) << std::endl;
  107. for (;;)
  108. {
  109. std::vector<V> result;
  110. result.reserve(100);
  111. B result_one;
  112. // packing test
  113. {
  114. clock_t::time_point start = clock_t::now();
  115. RT t(values.begin(), values.end());
  116. dur_t time = clock_t::now() - start;
  117. std::cout << time << " - pack " << values_count /*<< '\n'*/;
  118. std::cout << (bgi::detail::rtree::utilities::are_levels_ok(t) ? " ok" : " NOK")
  119. << (bgi::detail::rtree::utilities::are_boxes_ok(t) ? " ok\n" : "NOK\n");
  120. {
  121. clock_t::time_point start = clock_t::now();
  122. size_t temp = 0;
  123. for (size_t i = 0 ; i < queries_count ; ++i )
  124. {
  125. float x = coords[i].first;
  126. float y = coords[i].second;
  127. result.clear();
  128. t.query(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10))), std::back_inserter(result));
  129. temp += result.size();
  130. }
  131. dur_t time = clock_t::now() - start;
  132. std::cout << time << " - query(B) " << queries_count << " found " << temp << '\n';
  133. }
  134. }
  135. RT t;
  136. // inserting test
  137. {
  138. clock_t::time_point start = clock_t::now();
  139. t.insert(values);
  140. dur_t time = clock_t::now() - start;
  141. std::cout << time << " - insert " << values_count /*<< '\n'*/;
  142. std::cout << (bgi::detail::rtree::utilities::are_levels_ok(t) ? " ok" : " NOK")
  143. << (bgi::detail::rtree::utilities::are_boxes_ok(t) ? " ok\n" : "NOK\n");
  144. }
  145. {
  146. clock_t::time_point start = clock_t::now();
  147. size_t temp = 0;
  148. for (size_t i = 0 ; i < queries_count ; ++i )
  149. {
  150. float x = coords[i].first;
  151. float y = coords[i].second;
  152. result.clear();
  153. t.query(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10))), std::back_inserter(result));
  154. temp += result.size();
  155. }
  156. dur_t time = clock_t::now() - start;
  157. std::cout << time << " - query(B) " << queries_count << " found " << temp << '\n';
  158. }
  159. {
  160. clock_t::time_point start = clock_t::now();
  161. size_t temp = 0;
  162. for (size_t i = 0 ; i < queries_count ; ++i )
  163. {
  164. float x = coords[i].first;
  165. float y = coords[i].second;
  166. result.clear();
  167. boost::copy(t | bgi::adaptors::queried(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))),
  168. std::back_inserter(result));
  169. temp += result.size();
  170. }
  171. dur_t time = clock_t::now() - start;
  172. std::cout << time << " - range queried(B) " << queries_count << " found " << temp << '\n';
  173. }
  174. #ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
  175. {
  176. clock_t::time_point start = clock_t::now();
  177. size_t temp = 0;
  178. for (size_t i = 0 ; i < queries_count ; ++i )
  179. {
  180. float x = coords[i].first;
  181. float y = coords[i].second;
  182. result.clear();
  183. std::copy(
  184. t.qbegin_(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))),
  185. t.qend_(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))),
  186. std::back_inserter(result));
  187. temp += result.size();
  188. }
  189. dur_t time = clock_t::now() - start;
  190. std::cout << time << " - qbegin(B) qend(B) " << queries_count << " found " << temp << '\n';
  191. }
  192. {
  193. clock_t::time_point start = clock_t::now();
  194. size_t temp = 0;
  195. for (size_t i = 0 ; i < queries_count ; ++i )
  196. {
  197. float x = coords[i].first;
  198. float y = coords[i].second;
  199. result.clear();
  200. mycopy(
  201. t.qbegin_(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))),
  202. t.qend_(),
  203. std::back_inserter(result));
  204. temp += result.size();
  205. }
  206. dur_t time = clock_t::now() - start;
  207. std::cout << time << " - qbegin(B) qend() " << queries_count << " found " << temp << '\n';
  208. }
  209. {
  210. clock_t::time_point start = clock_t::now();
  211. size_t temp = 0;
  212. for (size_t i = 0 ; i < queries_count ; ++i )
  213. {
  214. float x = coords[i].first;
  215. float y = coords[i].second;
  216. result.clear();
  217. boost::copy(
  218. std::make_pair(
  219. t.qbegin_(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))),
  220. t.qend_(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10))))
  221. ), std::back_inserter(result));
  222. temp += result.size();
  223. }
  224. dur_t time = clock_t::now() - start;
  225. std::cout << time << " - range qbegin(B) qend(B)" << queries_count << " found " << temp << '\n';
  226. }
  227. #endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
  228. {
  229. clock_t::time_point start = clock_t::now();
  230. size_t temp = 0;
  231. for (size_t i = 0 ; i < queries_count ; ++i )
  232. {
  233. float x = coords[i].first;
  234. float y = coords[i].second;
  235. result.clear();
  236. RT::const_query_iterator first = t.qbegin(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10))));
  237. RT::const_query_iterator last = t.qend();
  238. std::copy(first, last, std::back_inserter(result));
  239. temp += result.size();
  240. }
  241. dur_t time = clock_t::now() - start;
  242. std::cout << time << " - type-erased qbegin(B) qend() " << queries_count << " found " << temp << '\n';
  243. }
  244. {
  245. clock_t::time_point start = clock_t::now();
  246. size_t temp = 0;
  247. for (size_t i = 0 ; i < queries_count ; ++i )
  248. {
  249. float x = coords[i].first;
  250. float y = coords[i].second;
  251. result.clear();
  252. RT::const_query_iterator first = t.qbegin(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10))));
  253. RT::const_query_iterator last = t.qend();
  254. boost::copy(std::make_pair(first, last), std::back_inserter(result));
  255. temp += result.size();
  256. }
  257. dur_t time = clock_t::now() - start;
  258. std::cout << time << " - range type-erased qbegin(B) qend() " << queries_count << " found " << temp << '\n';
  259. }
  260. #ifndef SEGMENT_INDEXABLE
  261. {
  262. clock_t::time_point start = clock_t::now();
  263. size_t temp = 0;
  264. for (size_t i = 0 ; i < queries_count / 2 ; ++i )
  265. {
  266. float x1 = coords[i].first;
  267. float y1 = coords[i].second;
  268. float x2 = coords[i+1].first;
  269. float y2 = coords[i+1].second;
  270. float x3 = coords[i+2].first;
  271. float y3 = coords[i+2].second;
  272. result.clear();
  273. t.query(
  274. bgi::intersects(B(P(x1 - 10, y1 - 10), P(x1 + 10, y1 + 10)))
  275. &&
  276. !bgi::within(B(P(x2 - 10, y2 - 10), P(x2 + 10, y2 + 10)))
  277. &&
  278. !bgi::covered_by(B(P(x3 - 10, y3 - 10), P(x3 + 10, y3 + 10)))
  279. ,
  280. std::back_inserter(result)
  281. );
  282. temp += result.size();
  283. }
  284. dur_t time = clock_t::now() - start;
  285. std::cout << time << " - query(i && !w && !c) " << queries_count << " found " << temp << '\n';
  286. }
  287. #endif
  288. result.clear();
  289. {
  290. clock_t::time_point start = clock_t::now();
  291. size_t temp = 0;
  292. for (size_t i = 0 ; i < nearest_queries_count ; ++i )
  293. {
  294. float x = coords[i].first + 100;
  295. float y = coords[i].second + 100;
  296. result.clear();
  297. temp += t.query(bgi::nearest(P(x, y), neighbours_count), std::back_inserter(result));
  298. }
  299. dur_t time = clock_t::now() - start;
  300. std::cout << time << " - query(nearest(P, " << neighbours_count << ")) " << nearest_queries_count << " found " << temp << '\n';
  301. }
  302. #ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
  303. {
  304. clock_t::time_point start = clock_t::now();
  305. size_t temp = 0;
  306. for (size_t i = 0 ; i < nearest_queries_count ; ++i )
  307. {
  308. float x = coords[i].first + 100;
  309. float y = coords[i].second + 100;
  310. result.clear();
  311. std::copy(
  312. t.qbegin_(bgi::nearest(P(x, y), neighbours_count)),
  313. t.qend_(bgi::nearest(P(x, y), neighbours_count)),
  314. std::back_inserter(result));
  315. temp += result.size();
  316. }
  317. dur_t time = clock_t::now() - start;
  318. std::cout << time << " - qbegin(nearest(P, " << neighbours_count << ")) qend(n) " << nearest_queries_count << " found " << temp << '\n';
  319. }
  320. {
  321. clock_t::time_point start = clock_t::now();
  322. size_t temp = 0;
  323. for (size_t i = 0 ; i < nearest_queries_count ; ++i )
  324. {
  325. float x = coords[i].first + 100;
  326. float y = coords[i].second + 100;
  327. result.clear();
  328. mycopy(
  329. t.qbegin_(bgi::nearest(P(x, y), neighbours_count)),
  330. t.qend_(),
  331. std::back_inserter(result));
  332. temp += result.size();
  333. }
  334. dur_t time = clock_t::now() - start;
  335. std::cout << time << " - qbegin(nearest(P, " << neighbours_count << ")) qend() " << nearest_queries_count << " found " << temp << '\n';
  336. }
  337. #endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
  338. {
  339. clock_t::time_point start = clock_t::now();
  340. size_t temp = 0;
  341. for (size_t i = 0 ; i < nearest_queries_count ; ++i )
  342. {
  343. float x = coords[i].first;
  344. float y = coords[i].second;
  345. result.clear();
  346. RT::const_query_iterator first = t.qbegin(bgi::nearest(P(x, y), neighbours_count));
  347. RT::const_query_iterator last = t.qend();
  348. std::copy(first, last, std::back_inserter(result));
  349. temp += result.size();
  350. }
  351. dur_t time = clock_t::now() - start;
  352. std::cout << time << " - type-erased qbegin(nearest(P, " << neighbours_count << ")) qend() " << nearest_queries_count << " found " << temp << '\n';
  353. }
  354. #ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
  355. #ifndef SEGMENT_INDEXABLE
  356. {
  357. LS ls;
  358. ls.resize(6);
  359. clock_t::time_point start = clock_t::now();
  360. size_t temp = 0;
  361. for (size_t i = 0 ; i < path_queries_count ; ++i )
  362. {
  363. float x = coords[i].first;
  364. float y = coords[i].second;
  365. for ( int i = 0 ; i < 3 ; ++i )
  366. {
  367. float foo = i*max_val/300;
  368. ls[2*i] = P(x, y+foo);
  369. ls[2*i+1] = P(x+max_val/100, y+foo);
  370. }
  371. result.clear();
  372. t.query(bgi::path(ls, path_values_count), std::back_inserter(result));
  373. temp += result.size();
  374. }
  375. dur_t time = clock_t::now() - start;
  376. std::cout << time << " - query(path(LS6, " << path_values_count << ")) " << path_queries_count << " found " << temp << '\n';
  377. }
  378. {
  379. LS ls;
  380. ls.resize(2);
  381. clock_t::time_point start = clock_t::now();
  382. size_t temp = 0;
  383. for (size_t i = 0 ; i < path_queries_count2 ; ++i )
  384. {
  385. float x = coords[i].first;
  386. float y = coords[i].second;
  387. ls[0] = P(x, y);
  388. ls[1] = P(x+max_val/100, y+max_val/100);
  389. result.clear();
  390. t.query(bgi::path(ls, path_values_count), std::back_inserter(result));
  391. temp += result.size();
  392. }
  393. dur_t time = clock_t::now() - start;
  394. std::cout << time << " - query(path(LS2, " << path_values_count << ")) " << path_queries_count2 << " found " << temp << '\n';
  395. }
  396. {
  397. clock_t::time_point start = clock_t::now();
  398. size_t temp = 0;
  399. for (size_t i = 0 ; i < path_queries_count2 ; ++i )
  400. {
  401. float x = coords[i].first;
  402. float y = coords[i].second;
  403. S seg(P(x, y), P(x+max_val/100, y+max_val/100));
  404. result.clear();
  405. t.query(bgi::path(seg, path_values_count), std::back_inserter(result));
  406. temp += result.size();
  407. }
  408. dur_t time = clock_t::now() - start;
  409. std::cout << time << " - query(path(S, " << path_values_count << ")) " << path_queries_count2 << " found " << temp << '\n';
  410. }
  411. #endif
  412. #endif
  413. {
  414. clock_t::time_point start = clock_t::now();
  415. for (size_t i = 0 ; i < values_count / 10 ; ++i )
  416. {
  417. float x = coords[i].first;
  418. float y = coords[i].second;
  419. t.remove(generate_value<V>::apply(x, y));
  420. }
  421. dur_t time = clock_t::now() - start;
  422. std::cout << time << " - remove " << values_count / 10 << '\n';
  423. std::cout << (bgi::detail::rtree::utilities::are_boxes_ok(t) ? " boxes ok\n" : "boxes NOT ok\n");
  424. }
  425. std::cout << "------------------------------------------------\n";
  426. }
  427. return 0;
  428. }