performance_switch.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // Copyright Oliver Kowalke 2014.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. #include <cstdlib>
  6. #include <iostream>
  7. #include <stdexcept>
  8. #include <string>
  9. #include <boost/chrono.hpp>
  10. #include <boost/coroutine2/all.hpp>
  11. #include <boost/cstdint.hpp>
  12. #include <boost/program_options.hpp>
  13. #include "../bind_processor.hpp"
  14. #include "../clock.hpp"
  15. #include "../cycle.hpp"
  16. boost::uint64_t jobs = 1000;
  17. struct X
  18. {
  19. std::string str;
  20. X( std::string const& str_) :
  21. str( str_)
  22. {}
  23. };
  24. const X x("abc");
  25. void fn_void( boost::coroutines2::coroutine< void >::push_type & c)
  26. { while ( true) c(); }
  27. void fn_int( boost::coroutines2::coroutine< int >::push_type & c)
  28. { while ( true) c( 7); }
  29. void fn_x( boost::coroutines2::coroutine< X >::push_type & c)
  30. {
  31. while ( true) c( x);
  32. }
  33. duration_type measure_time_void( duration_type overhead)
  34. {
  35. boost::coroutines2::segmented_stack stack_alloc;
  36. boost::coroutines2::coroutine< void >::pull_type c( stack_alloc, fn_void);
  37. time_point_type start( clock_type::now() );
  38. for ( std::size_t i = 0; i < jobs; ++i) {
  39. c();
  40. }
  41. duration_type total = clock_type::now() - start;
  42. total -= overhead_clock(); // overhead of measurement
  43. total /= jobs; // loops
  44. total /= 2; // 2x jump_fcontext
  45. return total;
  46. }
  47. duration_type measure_time_int( duration_type overhead)
  48. {
  49. boost::coroutines2::segmented_stack stack_alloc;
  50. boost::coroutines2::coroutine< int >::pull_type c( stack_alloc, fn_int);
  51. time_point_type start( clock_type::now() );
  52. for ( std::size_t i = 0; i < jobs; ++i) {
  53. c();
  54. }
  55. duration_type total = clock_type::now() - start;
  56. total -= overhead_clock(); // overhead of measurement
  57. total /= jobs; // loops
  58. total /= 2; // 2x jump_fcontext
  59. return total;
  60. }
  61. duration_type measure_time_x( duration_type overhead)
  62. {
  63. boost::coroutines2::segmented_stack stack_alloc;
  64. boost::coroutines2::coroutine< X >::pull_type c( stack_alloc, fn_x);
  65. time_point_type start( clock_type::now() );
  66. for ( std::size_t i = 0; i < jobs; ++i) {
  67. c();
  68. }
  69. duration_type total = clock_type::now() - start;
  70. total -= overhead_clock(); // overhead of measurement
  71. total /= jobs; // loops
  72. total /= 2; // 2x jump_fcontext
  73. return total;
  74. }
  75. # ifdef BOOST_CONTEXT_CYCLE
  76. cycle_type measure_cycles_void( cycle_type overhead)
  77. {
  78. boost::coroutines2::segmented_stack stack_alloc;
  79. boost::coroutines2::coroutine< void >::pull_type c( stack_alloc, fn_void);
  80. cycle_type start( cycles() );
  81. for ( std::size_t i = 0; i < jobs; ++i) {
  82. c();
  83. }
  84. cycle_type total = cycles() - start;
  85. total -= overhead; // overhead of measurement
  86. total /= jobs; // loops
  87. total /= 2; // 2x jump_fcontext
  88. return total;
  89. }
  90. cycle_type measure_cycles_int( cycle_type overhead)
  91. {
  92. boost::coroutines2::segmented_stack stack_alloc;
  93. boost::coroutines2::coroutine< int >::pull_type c( stack_alloc, fn_int);
  94. cycle_type start( cycles() );
  95. for ( std::size_t i = 0; i < jobs; ++i) {
  96. c();
  97. }
  98. cycle_type total = cycles() - start;
  99. total -= overhead; // overhead of measurement
  100. total /= jobs; // loops
  101. total /= 2; // 2x jump_fcontext
  102. return total;
  103. }
  104. cycle_type measure_cycles_x( cycle_type overhead)
  105. {
  106. boost::coroutines2::segmented_stack stack_alloc;
  107. boost::coroutines2::coroutine< X >::pull_type c( stack_alloc, fn_x);
  108. cycle_type start( cycles() );
  109. for ( std::size_t i = 0; i < jobs; ++i) {
  110. c();
  111. }
  112. cycle_type total = cycles() - start;
  113. total -= overhead; // overhead of measurement
  114. total /= jobs; // loops
  115. total /= 2; // 2x jump_fcontext
  116. return total;
  117. }
  118. # endif
  119. int main( int argc, char * argv[])
  120. {
  121. try
  122. {
  123. bool bind = false;
  124. boost::program_options::options_description desc("allowed options");
  125. desc.add_options()
  126. ("help", "help message")
  127. ("bind,b", boost::program_options::value< bool >( & bind), "bind thread to CPU")
  128. ("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
  129. boost::program_options::variables_map vm;
  130. boost::program_options::store(
  131. boost::program_options::parse_command_line(
  132. argc,
  133. argv,
  134. desc),
  135. vm);
  136. boost::program_options::notify( vm);
  137. if ( vm.count("help") ) {
  138. std::cout << desc << std::endl;
  139. return EXIT_SUCCESS;
  140. }
  141. if ( bind) bind_to_processor( 0);
  142. duration_type overhead_c = overhead_clock();
  143. std::cout << "overhead " << overhead_c.count() << " nano seconds" << std::endl;
  144. boost::uint64_t res = measure_time_void( overhead_c).count();
  145. std::cout << "void: average of " << res << " nano seconds" << std::endl;
  146. res = measure_time_int( overhead_c).count();
  147. std::cout << "int: average of " << res << " nano seconds" << std::endl;
  148. res = measure_time_x( overhead_c).count();
  149. std::cout << "X: average of " << res << " nano seconds" << std::endl;
  150. #ifdef BOOST_CONTEXT_CYCLE
  151. cycle_type overhead_y = overhead_cycle();
  152. std::cout << "overhead " << overhead_y << " cpu cycles" << std::endl;
  153. res = measure_cycles_void( overhead_y);
  154. std::cout << "void: average of " << res << " cpu cycles" << std::endl;
  155. res = measure_cycles_int( overhead_y);
  156. std::cout << "int: average of " << res << " cpu cycles" << std::endl;
  157. res = measure_cycles_x( overhead_y);
  158. std::cout << "X: average of " << res << " cpu cycles" << std::endl;
  159. #endif
  160. return EXIT_SUCCESS;
  161. }
  162. catch ( std::exception const& e)
  163. { std::cerr << "exception: " << e.what() << std::endl; }
  164. catch (...)
  165. { std::cerr << "unhandled exception" << std::endl; }
  166. return EXIT_FAILURE;
  167. }