performance.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Copyright Oliver Kowalke 2009.
  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 <cstddef>
  6. #include <cstdlib>
  7. #include <iostream>
  8. #include <stdexcept>
  9. #include <boost/context/detail/fcontext.hpp>
  10. #include <boost/cstdint.hpp>
  11. #include <boost/program_options.hpp>
  12. #include "../clock.hpp"
  13. #include "../cycle.hpp"
  14. template< std::size_t Max, std::size_t Default, std::size_t Min >
  15. class simple_stack_allocator
  16. {
  17. public:
  18. static std::size_t maximum_stacksize()
  19. { return Max; }
  20. static std::size_t default_stacksize()
  21. { return Default; }
  22. static std::size_t minimum_stacksize()
  23. { return Min; }
  24. void * allocate( std::size_t size) const
  25. {
  26. BOOST_ASSERT( minimum_stacksize() <= size);
  27. BOOST_ASSERT( maximum_stacksize() >= size);
  28. void * limit = std::malloc( size);
  29. if ( ! limit) throw std::bad_alloc();
  30. return static_cast< char * >( limit) + size;
  31. }
  32. void deallocate( void * vp, std::size_t size) const
  33. {
  34. BOOST_ASSERT( vp);
  35. BOOST_ASSERT( minimum_stacksize() <= size);
  36. BOOST_ASSERT( maximum_stacksize() >= size);
  37. void * limit = static_cast< char * >( vp) - size;
  38. std::free( limit);
  39. }
  40. };
  41. typedef simple_stack_allocator<
  42. 8 * 1024 * 1024, 64 * 1024, 8 * 1024
  43. > stack_allocator;
  44. boost::uint64_t jobs = 1000000;
  45. static void foo( boost::context::detail::transfer_t t_) {
  46. boost::context::detail::transfer_t t = t_;
  47. while ( true) {
  48. t = boost::context::detail::jump_fcontext( t.fctx, 0);
  49. }
  50. }
  51. duration_type measure_time_fc() {
  52. stack_allocator stack_alloc;
  53. boost::context::detail::fcontext_t ctx = boost::context::detail::make_fcontext(
  54. stack_alloc.allocate( stack_allocator::default_stacksize() ),
  55. stack_allocator::default_stacksize(),
  56. foo);
  57. // cache warum-up
  58. boost::context::detail::transfer_t t = boost::context::detail::jump_fcontext( ctx, 0);
  59. time_point_type start( clock_type::now() );
  60. for ( std::size_t i = 0; i < jobs; ++i) {
  61. t = boost::context::detail::jump_fcontext( t.fctx, 0);
  62. }
  63. duration_type total = clock_type::now() - start;
  64. total -= overhead_clock(); // overhead of measurement
  65. total /= jobs; // loops
  66. total /= 2; // 2x jump_fcontext
  67. return total;
  68. }
  69. #ifdef BOOST_CONTEXT_CYCLE
  70. cycle_type measure_cycles_fc() {
  71. stack_allocator stack_alloc;
  72. boost::context::detail::fcontext_t ctx = boost::context::detail::make_fcontext(
  73. stack_alloc.allocate( stack_allocator::default_stacksize() ),
  74. stack_allocator::default_stacksize(),
  75. foo);
  76. // cache warum-up
  77. boost::context::detail::transfer_t t = boost::context::detail::jump_fcontext( ctx, 0);
  78. cycle_type start( cycles() );
  79. for ( std::size_t i = 0; i < jobs; ++i) {
  80. t = boost::context::detail::jump_fcontext( t.fctx, 0);
  81. }
  82. cycle_type total = cycles() - start;
  83. total -= overhead_cycle(); // overhead of measurement
  84. total /= jobs; // loops
  85. total /= 2; // 2x jump_fcontext
  86. return total;
  87. }
  88. #endif
  89. int main( int argc, char * argv[])
  90. {
  91. try
  92. {
  93. boost::program_options::options_description desc("allowed options");
  94. desc.add_options()
  95. ("help", "help message")
  96. ("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
  97. boost::program_options::variables_map vm;
  98. boost::program_options::store(
  99. boost::program_options::parse_command_line(
  100. argc,
  101. argv,
  102. desc),
  103. vm);
  104. boost::program_options::notify( vm);
  105. if ( vm.count("help") ) {
  106. std::cout << desc << std::endl;
  107. return EXIT_SUCCESS;
  108. }
  109. boost::uint64_t res = measure_time_fc().count();
  110. std::cout << "fcontext_t: average of " << res << " nano seconds" << std::endl;
  111. #ifdef BOOST_CONTEXT_CYCLE
  112. res = measure_cycles_fc();
  113. std::cout << "fcontext_t: average of " << res << " cpu cycles" << std::endl;
  114. #endif
  115. return EXIT_SUCCESS;
  116. }
  117. catch ( std::exception const& e)
  118. { std::cerr << "exception: " << e.what() << std::endl; }
  119. catch (...)
  120. { std::cerr << "unhandled exception" << std::endl; }
  121. return EXIT_FAILURE;
  122. }