bench_set.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2013-2014. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/container for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_CONTAINER_BENCH_BENCH_SET_HPP
  11. #define BOOST_CONTAINER_BENCH_BENCH_SET_HPP
  12. #include <iostream>
  13. #include <boost/timer/timer.hpp>
  14. #include <algorithm> //sort
  15. #include <exception>
  16. #include <sstream>
  17. #include <iomanip>
  18. #include <boost/container/vector.hpp>
  19. #include <boost/container/string.hpp>
  20. using boost::timer::cpu_timer;
  21. using boost::timer::cpu_times;
  22. using boost::timer::nanosecond_type;
  23. #define SIMPLE_IT
  24. #ifdef SIMPLE_IT
  25. static const std::size_t NIter = 3;
  26. #else
  27. #ifdef NDEBUG
  28. static const std::size_t NIter = 250;
  29. #else
  30. static const std::size_t NIter = 25;
  31. #endif
  32. #endif
  33. static const std::size_t NElements = 1000;
  34. void compare_times(cpu_times time_numerator, cpu_times time_denominator){
  35. std::cout << ((double)time_numerator.wall/(double)time_denominator.wall) << std::endl;
  36. std::cout << "----------------------------------------------" << '\n' << std::endl;
  37. }
  38. template< class RandomIt >
  39. void random_shuffle( RandomIt first, RandomIt last )
  40. {
  41. typedef typename boost::container::iterator_traits<RandomIt>::difference_type difference_type;
  42. difference_type n = last - first;
  43. for (difference_type i = n-1; i > 0; --i) {
  44. difference_type j = std::rand() % (i+1);
  45. if(j != i) {
  46. boost::adl_move_swap(first[i], first[j]);
  47. }
  48. }
  49. }
  50. boost::container::vector<int> sorted_unique_range_int;
  51. boost::container::vector<int> sorted_range_int;
  52. boost::container::vector<int> random_unique_range_int;
  53. boost::container::vector<int> random_range_int;
  54. void fill_range_ints()
  55. {
  56. //sorted_unique_range_int
  57. sorted_unique_range_int.resize(NElements);
  58. for(std::size_t i = 0, max = sorted_unique_range_int.size(); i != max; ++i){
  59. sorted_unique_range_int[i] = static_cast<int>(i);
  60. }
  61. //sorted_range_int
  62. sorted_range_int = sorted_unique_range_int;
  63. sorted_range_int.insert(sorted_range_int.end(), sorted_unique_range_int.begin(), sorted_unique_range_int.end());
  64. std::sort(sorted_range_int.begin(), sorted_range_int.end());
  65. //random_range_int
  66. std::srand(0);
  67. random_range_int.assign(sorted_range_int.begin(), sorted_range_int.end());
  68. ::random_shuffle(random_range_int.begin(), random_range_int.end());
  69. //random_unique_range_int
  70. std::srand(0);
  71. random_unique_range_int.assign(sorted_unique_range_int.begin(), sorted_unique_range_int.end());
  72. ::random_shuffle(random_unique_range_int.begin(), random_unique_range_int.end());
  73. }
  74. boost::container::vector<boost::container::string> sorted_unique_range_string;
  75. boost::container::vector<boost::container::string> sorted_range_string;
  76. boost::container::vector<boost::container::string> random_unique_range_string;
  77. boost::container::vector<boost::container::string> random_range_string;
  78. void fill_range_strings()
  79. {
  80. boost::container::string model_s;
  81. model_s.append(sizeof(boost::container::string), '*');
  82. //sorted_unique_range_int
  83. sorted_unique_range_string.resize(NElements);
  84. std::stringstream sstr;
  85. for(std::size_t i = 0, max = sorted_unique_range_string.size(); i != max; ++i){
  86. sstr.str(std::string());
  87. sstr << std::setfill('0') << std::setw(10) << i;
  88. sorted_unique_range_string[i] = model_s;
  89. const std::string &s = sstr.str();
  90. sorted_unique_range_string[i].append(s.begin(), s.end());
  91. }
  92. //sorted_range_string
  93. sorted_range_string = sorted_unique_range_string;
  94. sorted_range_string.insert(sorted_range_string.end(), sorted_unique_range_string.begin(), sorted_unique_range_string.end());
  95. std::sort(sorted_range_string.begin(), sorted_range_string.end());
  96. //random_range_string
  97. std::srand(0);
  98. random_range_string.assign(sorted_range_string.begin(), sorted_range_string.end());
  99. ::random_shuffle(random_range_string.begin(), random_range_string.end());
  100. //random_unique_range_string
  101. std::srand(0);
  102. random_unique_range_string.assign(sorted_unique_range_string.begin(), sorted_unique_range_string.end());
  103. ::random_shuffle(random_unique_range_string.begin(), random_unique_range_string.end());
  104. }
  105. template<class T>
  106. struct range_provider;
  107. template<>
  108. struct range_provider<int>
  109. {
  110. typedef boost::container::vector<int> type;
  111. static type &sorted_unique()
  112. { return sorted_unique_range_int; }
  113. static type &sorted()
  114. { return sorted_range_int; }
  115. static type &random_unique()
  116. { return random_unique_range_int; }
  117. static type &random()
  118. { return random_range_int; }
  119. };
  120. template<>
  121. struct range_provider<boost::container::string>
  122. {
  123. typedef boost::container::vector<boost::container::string> type;
  124. static type &sorted_unique()
  125. { return sorted_unique_range_string; }
  126. static type &sorted()
  127. { return sorted_range_string; }
  128. static type &random_unique()
  129. { return random_unique_range_string; }
  130. static type &random()
  131. { return random_range_string; }
  132. };
  133. template<typename C>
  134. cpu_times copy_destroy_time(boost::container::vector<typename C::value_type> &unique_range)
  135. {
  136. cpu_timer copy_timer, assign_timer, destroy_timer;
  137. cpu_timer total_time;
  138. for(std::size_t i = 0; i != NIter; ++i){
  139. {
  140. C c(unique_range.begin(), unique_range.end());
  141. total_time.resume();
  142. copy_timer.resume();
  143. C caux(c);
  144. copy_timer.stop();
  145. assign_timer.resume();
  146. c = caux;
  147. assign_timer.stop();
  148. destroy_timer.resume();
  149. }
  150. destroy_timer.stop();
  151. total_time.stop();
  152. }
  153. total_time.stop();
  154. std::cout << " Copy sorted range " << boost::timer::format(copy_timer.elapsed(), boost::timer::default_places, "%ws\n");
  155. std::cout << " Assign sorted range " << boost::timer::format(assign_timer.elapsed(), boost::timer::default_places, "%ws\n");
  156. std::cout << " Destroy " << boost::timer::format(destroy_timer.elapsed(), boost::timer::default_places, "%ws\n");
  157. std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws\n") << std::endl;
  158. return total_time.elapsed();
  159. }
  160. template<typename C>
  161. cpu_times construct_time( boost::container::vector<typename C::value_type> &unique_range
  162. , boost::container::vector<typename C::value_type> &range
  163. , const char *RangeType)
  164. {
  165. cpu_timer sur_timer, sr_timer;
  166. cpu_timer total_time;
  167. for(std::size_t i = 0; i != NIter; ++i){
  168. {
  169. sur_timer.resume();
  170. total_time.resume();
  171. C c(unique_range.begin(), unique_range.end());
  172. sur_timer.stop();
  173. total_time.stop();
  174. }
  175. {
  176. total_time.resume();
  177. sr_timer.resume();
  178. C c(range.begin(), range.end());
  179. sr_timer.stop();
  180. total_time.stop();
  181. }
  182. }
  183. std::cout << " Construct " << RangeType << " unique_range " << boost::timer::format(sur_timer.elapsed(), boost::timer::default_places, "%ws\n");
  184. std::cout << " Construct " << RangeType << " range " << boost::timer::format(sr_timer.elapsed(), boost::timer::default_places, "%ws\n");
  185. std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws\n") << std::endl;
  186. return total_time.elapsed();
  187. }
  188. template<typename C>
  189. cpu_times insert_time( boost::container::vector<typename C::value_type> &unique_range
  190. , boost::container::vector<typename C::value_type> &range
  191. , const char *RangeType)
  192. {
  193. cpu_timer ur_timer,r_timer;
  194. ur_timer.stop();r_timer.stop();
  195. cpu_timer total_time;
  196. total_time.resume();
  197. for(std::size_t i = 0; i != NIter; ++i){
  198. {
  199. total_time.resume();
  200. ur_timer.resume();
  201. C c;
  202. c.insert(unique_range.begin(), unique_range.end());
  203. ur_timer.stop();
  204. total_time.stop();
  205. }
  206. {
  207. total_time.resume();
  208. r_timer.resume();
  209. C c;
  210. c.insert(range.begin(), range.end());
  211. r_timer.stop();
  212. total_time.stop();
  213. }
  214. }
  215. std::cout << " Insert " << RangeType << " unique_range " << boost::timer::format(ur_timer.elapsed(), boost::timer::default_places, "%ws\n");
  216. std::cout << " Insert " << RangeType << " range " << boost::timer::format(r_timer.elapsed(), boost::timer::default_places, "%ws\n");
  217. std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws\n") << std::endl;
  218. return total_time.elapsed();
  219. }
  220. template<typename Iterator>
  221. bool check_not_end(boost::container::vector<Iterator> &iterators, Iterator itend, std::size_t number_of_ends = 0)
  222. {
  223. std::size_t end_count = 0;
  224. for(std::size_t i = 0, max = iterators.size(); i != max; ++i){
  225. if(iterators[i] == itend && (++end_count > number_of_ends) )
  226. return false;
  227. }
  228. return true;
  229. }
  230. template<typename Iterator>
  231. bool check_all_not_empty(boost::container::vector< std::pair<Iterator, Iterator > > &iterator_pairs)
  232. {
  233. for(std::size_t i = 0, max = iterator_pairs.size(); i != max; ++i){
  234. if(iterator_pairs[i].first == iterator_pairs[i].second)
  235. return false;
  236. }
  237. return true;
  238. }
  239. template<typename C>
  240. cpu_times search_time(boost::container::vector<typename C::value_type> &unique_range, const char *RangeType)
  241. {
  242. cpu_timer find_timer, lower_timer, upper_timer, equal_range_timer, count_timer;
  243. C c(unique_range.begin(), unique_range.end());
  244. cpu_timer total_time;
  245. total_time.resume();
  246. boost::container::vector<typename C::iterator> v_it(NElements);
  247. boost::container::vector< std::pair<typename C::iterator, typename C::iterator> > v_itp(NElements);
  248. for(std::size_t i = 0; i != NIter; ++i){
  249. //Find
  250. {
  251. find_timer.resume();
  252. for(std::size_t rep = 0; rep != 2; ++rep)
  253. for(std::size_t j = 0, max = unique_range.size(); j != max; ++j){
  254. v_it[j] = c.find(unique_range[j]);
  255. }
  256. find_timer.stop();
  257. if(!check_not_end(v_it, c.end())){
  258. std::cout << "ERROR! find all elements not found" << std::endl;
  259. }
  260. }
  261. //Lower
  262. {
  263. lower_timer.resume();
  264. for(std::size_t rep = 0; rep != 2; ++rep)
  265. for(std::size_t j = 0, max = unique_range.size(); j != max; ++j){
  266. v_it[j] = c.lower_bound(unique_range[j]);
  267. }
  268. lower_timer.stop();
  269. if(!check_not_end(v_it, c.end())){
  270. std::cout << "ERROR! lower_bound all elements not found" << std::endl;
  271. }
  272. }
  273. //Upper
  274. {
  275. upper_timer.resume();
  276. for(std::size_t rep = 0; rep != 2; ++rep)
  277. for(std::size_t j = 0, max = unique_range.size(); j != max; ++j){
  278. v_it[j] = c.upper_bound(unique_range[j]);
  279. }
  280. upper_timer.stop();
  281. if(!check_not_end(v_it, c.end(), 1u)){
  282. std::cout << "ERROR! upper_bound all elements not found" << std::endl;
  283. }
  284. }
  285. //Equal
  286. {
  287. equal_range_timer.resume();
  288. for(std::size_t rep = 0; rep != 2; ++rep)
  289. for(std::size_t j = 0, max = unique_range.size(); j != max; ++j){
  290. v_itp[j] = c.equal_range(unique_range[j]);
  291. }
  292. equal_range_timer.stop();
  293. if(!check_all_not_empty(v_itp)){
  294. std::cout << "ERROR! equal_range all elements not found" << std::endl;
  295. }
  296. }
  297. //Count
  298. {
  299. std::size_t count = 0;
  300. count_timer.resume();
  301. for(std::size_t rep = 0; rep != 2; ++rep)
  302. for(std::size_t j = 0, max = unique_range.size(); j != max; ++j){
  303. count += c.count(unique_range[j]);
  304. }
  305. count_timer.stop();
  306. if(count/2 != c.size()){
  307. std::cout << "ERROR! count all elements not found" << std::endl;
  308. }
  309. }
  310. }
  311. total_time.stop();
  312. std::cout << " Find " << RangeType << " " << boost::timer::format(find_timer.elapsed(), boost::timer::default_places, "%ws\n");
  313. std::cout << " Lower Bound " << RangeType << " " << boost::timer::format(lower_timer.elapsed(), boost::timer::default_places, "%ws\n");
  314. std::cout << " Upper Bound " << RangeType << " " << boost::timer::format(upper_timer.elapsed(), boost::timer::default_places, "%ws\n");
  315. std::cout << " Equal Range " << RangeType << " " << boost::timer::format(equal_range_timer.elapsed(), boost::timer::default_places, "%ws\n");
  316. std::cout << " Count " << RangeType << " " << boost::timer::format(count_timer.elapsed(), boost::timer::default_places, "%ws\n");
  317. std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws\n") << std::endl;
  318. return total_time.elapsed();
  319. }
  320. template<typename C>
  321. void extensions_time(boost::container::vector<typename C::value_type> &sorted_unique_range)
  322. {
  323. cpu_timer sur_timer,sur_opt_timer;
  324. sur_timer.stop();sur_opt_timer.stop();
  325. for(std::size_t i = 0; i != NIter; ++i){
  326. {
  327. sur_timer.resume();
  328. C c(sorted_unique_range.begin(), sorted_unique_range.end());
  329. sur_timer.stop();
  330. }
  331. {
  332. sur_opt_timer.resume();
  333. C c(boost::container::ordered_unique_range, sorted_unique_range.begin(), sorted_unique_range.end());
  334. sur_opt_timer.stop();
  335. }
  336. }
  337. std::cout << " Construct sorted_unique_range " << boost::timer::format(sur_timer.elapsed(), boost::timer::default_places, "%ws\n");
  338. std::cout << " Construct sorted_unique_range (extension) " << boost::timer::format(sur_opt_timer.elapsed(), boost::timer::default_places, "%ws\n");
  339. std::cout << "Extension/Standard: ";
  340. compare_times(sur_opt_timer.elapsed(), sur_timer.elapsed());
  341. }
  342. template<class BoostClass, class StdClass>
  343. void launch_tests(const char *BoostContName, const char *StdContName)
  344. {
  345. typedef range_provider<typename BoostClass::value_type> get_range_t;
  346. try {
  347. std::cout << "**********************************************" << '\n';
  348. std::cout << "**********************************************" << '\n';
  349. std::cout << '\n';
  350. std::cout << BoostContName << " .VS " << StdContName << '\n';
  351. std::cout << '\n';
  352. std::cout << "**********************************************" << '\n';
  353. std::cout << "**********************************************" << '\n' << std::endl;
  354. {
  355. std::cout << "Copy/Assign/Destroy benchmark:" << BoostContName << std::endl;
  356. cpu_times boost_set_time = copy_destroy_time< BoostClass >(get_range_t::sorted_unique());
  357. std::cout << "Copy/Assign/Destroy benchmark:" << StdContName << std::endl;
  358. cpu_times std_set_time = copy_destroy_time< StdClass >(get_range_t::sorted_unique());
  359. std::cout << BoostContName << "/" << StdContName << ": ";
  360. compare_times(boost_set_time, std_set_time);
  361. }
  362. {
  363. std::cout << "Ordered construct benchmark:" << BoostContName << std::endl;
  364. cpu_times boost_set_time = construct_time< BoostClass >(get_range_t::sorted_unique(), get_range_t::sorted(), "(ord)");
  365. std::cout << "Ordered construct benchmark:" << StdContName << std::endl;
  366. cpu_times std_set_time = construct_time< StdClass >(get_range_t::sorted_unique(), get_range_t::sorted(), "(ord)");;
  367. std::cout << BoostContName << "/" << StdContName << ": ";
  368. compare_times(boost_set_time, std_set_time);
  369. }
  370. {
  371. std::cout << "Random construct benchmark:" << BoostContName << std::endl;
  372. cpu_times boost_set_time = construct_time< BoostClass >(get_range_t::random_unique(), get_range_t::random(), "(rnd)");
  373. std::cout << "Random construct benchmark:" << StdContName << std::endl;
  374. cpu_times std_set_time = construct_time< StdClass >(get_range_t::random_unique(), get_range_t::random(), "(rnd)");;
  375. std::cout << BoostContName << "/" << StdContName << ": ";
  376. compare_times(boost_set_time, std_set_time);
  377. }
  378. {
  379. std::cout << "Ordered Insert benchmark:" << BoostContName << std::endl;
  380. cpu_times boost_set_time = insert_time< BoostClass >(get_range_t::sorted_unique(), get_range_t::sorted(), "(ord)");
  381. std::cout << "Ordered Insert benchmark:" << StdContName << std::endl;
  382. cpu_times std_set_time = insert_time< StdClass >(get_range_t::sorted_unique(), get_range_t::sorted(), "(ord)");
  383. std::cout << BoostContName << "/" << StdContName << ": ";
  384. compare_times(boost_set_time, std_set_time);
  385. }
  386. {
  387. std::cout << "Random Insert benchmark:" << BoostContName << std::endl;
  388. cpu_times boost_set_time = insert_time< BoostClass >(get_range_t::random_unique(), get_range_t::random(), "(rnd)");
  389. std::cout << "Random Insert benchmark:" << StdContName << std::endl;
  390. cpu_times std_set_time = insert_time< StdClass >(get_range_t::random_unique(), get_range_t::random(), "(rnd)");
  391. std::cout << BoostContName << "/" << StdContName << ": ";
  392. compare_times(boost_set_time, std_set_time);
  393. }
  394. {
  395. std::cout << "Ordered Search benchmark:" << BoostContName << std::endl;
  396. cpu_times boost_set_time = search_time< BoostClass >(get_range_t::sorted_unique(), "(ord)");
  397. std::cout << "Ordered Search benchmark:" << StdContName << std::endl;
  398. cpu_times std_set_time = search_time< StdClass >(get_range_t::sorted_unique(), "(ord)");
  399. std::cout << BoostContName << "/" << StdContName << ": ";
  400. compare_times(boost_set_time, std_set_time);
  401. }
  402. {
  403. std::cout << "Random Search benchmark:" << BoostContName << std::endl;
  404. cpu_times boost_set_time = search_time< BoostClass >(get_range_t::random_unique(), "(rnd)");
  405. std::cout << "Random Search benchmark:" << StdContName << std::endl;
  406. cpu_times std_set_time = search_time< StdClass >(get_range_t::random_unique(), "(rnd)");
  407. std::cout << BoostContName << "/" << StdContName << ": ";
  408. compare_times(boost_set_time, std_set_time);
  409. }
  410. {
  411. std::cout << "Extensions benchmark:" << BoostContName << std::endl;
  412. extensions_time< BoostClass >(get_range_t::sorted_unique());
  413. }
  414. }catch(std::exception &e){
  415. std::cout << e.what();
  416. }
  417. }
  418. #endif //#ifndef BOOST_CONTAINER_BENCH_BENCH_SET_HPP