loop_time_test.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. // loop_time_test.cpp ----------------------------------------------------------------//
  2. // Copyright Beman Dawes 2013
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // http://www.boost.org/LICENSE_1_0.txt
  5. //--------------------------------------------------------------------------------------//
  6. //#define BOOST_ENDIAN_NO_INTRINSICS
  7. #include <boost/endian/detail/disable_warnings.hpp>
  8. #include <boost/endian/conversion.hpp>
  9. #include <boost/endian/arithmetic.hpp>
  10. #include <boost/cstdint.hpp>
  11. #include <boost/timer/timer.hpp>
  12. #include <iostream>
  13. #include <cstdlib>
  14. #include <string>
  15. #include <boost/detail/lightweight_main.hpp>
  16. #ifdef _MSC_VER
  17. # pragma warning (push)
  18. # pragma warning (disable : 4459)
  19. #endif
  20. #include <boost/lexical_cast.hpp>
  21. #ifdef _MSC_VER
  22. # pragma warning (pop)
  23. #endif
  24. using namespace boost;
  25. using namespace boost::endian;
  26. using std::cout;
  27. using std::endl;
  28. namespace
  29. {
  30. typedef boost::timer::nanosecond_type nanosecond_t;
  31. std::string command_args;
  32. uint64_t n; // number of test cases to run
  33. int places = 2; // decimal places for times
  34. bool verbose (false);
  35. bool time_aligned (true);
  36. bool time_unaligned (true);
  37. bool time_16(true);
  38. bool time_32(true);
  39. bool time_64(true);
  40. void process_command_line(int argc, char * argv[])
  41. {
  42. for (int a = 0; a < argc; ++a)
  43. {
  44. command_args += argv[a];
  45. if (a != argc-1)
  46. command_args += ' ';
  47. }
  48. // cout << command_args << '\n';;
  49. if (argc >=2)
  50. #ifndef _MSC_VER
  51. n = atoll(argv[1]);
  52. #else
  53. n = _atoi64(argv[1]);
  54. #endif
  55. for (; argc > 2; ++argv, --argc)
  56. {
  57. if ( *(argv[2]+1) == 'p' )
  58. places = atoi( argv[2]+2 );
  59. else if (*(argv[2] + 1) == 'v')
  60. verbose = true;
  61. else if (*(argv[2] + 1) == 'a')
  62. time_unaligned = false;
  63. else if (*(argv[2] + 1) == 'u')
  64. time_aligned = false;
  65. else if (*(argv[2] + 1) == '1')
  66. time_32 = time_64 = false;
  67. else if (*(argv[2] + 1) == '3')
  68. time_16 = time_64 = false;
  69. else if (*(argv[2] + 1) == '6')
  70. time_16 = time_32 = false;
  71. else
  72. {
  73. cout << "Error - unknown option: " << argv[2] << "\n\n";
  74. argc = -1;
  75. break;
  76. }
  77. }
  78. if (argc < 2)
  79. {
  80. cout << "Usage: loop_time_test n [Options]\n"
  81. " The argument n specifies the number of test cases to run\n"
  82. " Options:\n"
  83. " -v Verbose messages\n"
  84. " -p# Decimal places for times; default -p" << places << "\n"
  85. " -a Aligned tests only\n"
  86. " -u Unaligned tests only\n"
  87. " -16 16-bit tests only\n"
  88. " -32 32-bit tests only\n"
  89. " -64 64-bit tests only\n"
  90. ;
  91. return std::exit(1);
  92. }
  93. }
  94. std::string with_digit_separator(int64_t x)
  95. {
  96. std::string s = boost::lexical_cast<std::string>(x);
  97. std::string s2;
  98. for (std::string::size_type i = 0; i < s.size(); ++i)
  99. {
  100. if (i && ((s.size()-i) % 3) == 0)
  101. s2 += '\'';
  102. s2 += s[i];
  103. }
  104. return s2;
  105. }
  106. //--------------------------------------------------------------------------------------//
  107. template <class T, class EndianT>
  108. void time()
  109. {
  110. T total = 0;
  111. {
  112. // cout << "*************Endian integer approach...\n";
  113. EndianT x(0);
  114. boost::timer::cpu_timer t;
  115. for (uint64_t i = 0; i < n; ++i)
  116. {
  117. x += static_cast<T>(i);
  118. }
  119. t.stop();
  120. total += x;
  121. cout << "<td align=\"right\">" << t.format(places, "%t") << " s</td>";
  122. }
  123. {
  124. // cout << "***************Endian conversion approach...\n";
  125. T x(0);
  126. boost::timer::cpu_timer t;
  127. native_to_big_inplace(x);
  128. for (uint64_t i = 0; i < n; ++i)
  129. {
  130. x += static_cast<T>(i);
  131. }
  132. big_to_native_inplace(x);
  133. t.stop();
  134. native_to_big_inplace(x);
  135. if (x != total)
  136. throw std::logic_error("integer approach total != conversion approach total");
  137. cout << "<td align=\"right\">" << t.format(places, "%t") << " s</td>";
  138. }
  139. }
  140. void test_big_align_int16()
  141. {
  142. cout << "<tr><td>16-bit aligned big endian</td>";
  143. time<int16_t, big_int16_at>();
  144. cout << "</tr>\n";
  145. }
  146. void test_little_align_int16()
  147. {
  148. cout << "<tr><td>16-bit aligned little endian</td>";
  149. time<int16_t, little_int16_at>();
  150. cout << "</tr>\n";
  151. }
  152. void test_big_int16()
  153. {
  154. cout << "<tr><td>16-bit unaligned big endian</td>";
  155. time<int16_t, big_int16_t>();
  156. cout << "</tr>\n";
  157. }
  158. void test_little_int16()
  159. {
  160. cout << "<tr><td>16-bit unaligned little endian</td>";
  161. time<int16_t, little_int16_t>();
  162. cout << "</tr>\n";
  163. }
  164. void test_big_align_int32()
  165. {
  166. cout << "<tr><td>32-bit aligned big endian</td>";
  167. time<int32_t, big_int32_at>();
  168. cout << "</tr>\n";
  169. }
  170. void test_little_align_int32()
  171. {
  172. cout << "<tr><td>32-bit aligned little endian</td>";
  173. time<int32_t, little_int32_at>();
  174. cout << "</tr>\n";
  175. }
  176. void test_big_int32()
  177. {
  178. cout << "<tr><td>32-bit unaligned big endian</td>";
  179. time<int32_t, big_int32_t>();
  180. cout << "</tr>\n";
  181. }
  182. void test_little_int32()
  183. {
  184. cout << "<tr><td>32-bit unaligned little endian</td>";
  185. time<int32_t, little_int32_t>();
  186. cout << "</tr>\n";
  187. }
  188. void test_big_align_int64()
  189. {
  190. cout << "<tr><td>64-bit aligned big endian</td>";
  191. time<int64_t, big_int64_at>();
  192. cout << "</tr>\n";
  193. }
  194. void test_little_align_int64()
  195. {
  196. cout << "<tr><td>64-bit aligned little endian</td>";
  197. time<int64_t, little_int64_at>();
  198. cout << "</tr>\n";
  199. }
  200. void test_big_int64()
  201. {
  202. cout << "<tr><td>64-bit unaligned big endian</td>";
  203. time<int64_t, big_int64_t>();
  204. cout << "</tr>\n";
  205. }
  206. void test_little_int64()
  207. {
  208. cout << "<tr><td>64-bit unaligned little endian</td>";
  209. time<int64_t, little_int64_t>();
  210. cout << "</tr>\n";
  211. }
  212. } // unnamed namespace
  213. //--------------------------------------------------------------------------------------//
  214. int cpp_main(int argc, char* argv[])
  215. {
  216. process_command_line(argc, argv);
  217. cout
  218. << "<html>\n<head>\n<title>Endian Loop Time Test</title>\n</head>\n<body>\n"
  219. << "<!-- boost-no-inspect -->\n"
  220. << "<div align=\"center\"> <center>\n"
  221. << "<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\""
  222. << "style=\"border-collapse: collapse\" bordercolor=\"#111111\">\n"
  223. << "<tr><td colspan=\"6\" align=\"center\"><b>"
  224. << BOOST_COMPILER << "</b></td></tr>\n"
  225. << "<tr><td colspan=\"6\" align=\"center\"><b>"
  226. << " Iterations: " << with_digit_separator(n)
  227. << ", Intrinsics: " BOOST_ENDIAN_INTRINSIC_MSG
  228. << "</b></td></tr>\n"
  229. << "<tr><td><b>Test Case</b></td>\n"
  230. "<td align=\"center\"><b>Endian<br>arithmetic<br>type</b></td>\n"
  231. "<td align=\"center\"><b>Endian<br>conversion<br>function</b></td>\n"
  232. "</tr>\n"
  233. ;
  234. if (time_aligned)
  235. {
  236. if (time_16)
  237. {
  238. test_big_align_int16();
  239. test_little_align_int16();
  240. }
  241. if (time_32)
  242. {
  243. test_big_align_int32();
  244. test_little_align_int32();
  245. }
  246. if (time_64)
  247. {
  248. test_big_align_int64();
  249. test_little_align_int64();
  250. }
  251. }
  252. if (time_unaligned)
  253. {
  254. if (time_16)
  255. {
  256. test_big_int16();
  257. test_little_int16();
  258. }
  259. if (time_32)
  260. {
  261. test_big_int32();
  262. test_little_int32();
  263. }
  264. if (time_64)
  265. {
  266. test_big_int64();
  267. test_little_int64();
  268. }
  269. }
  270. cout << "\n</div> </center>\n"
  271. << "\n</table>\n</body>\n</html>\n";
  272. return 0;
  273. }
  274. #include <boost/endian/detail/disable_warnings_pop.hpp>