2 // Copyright Oliver Kowalke 2009.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
11 #include <boost/chrono.hpp>
12 #include <boost/coroutine/all.hpp>
13 #include <boost/cstdint.hpp>
14 #include <boost/program_options.hpp>
16 #include "../bind_processor.hpp"
17 #include "../clock.hpp"
18 #include "../cycle.hpp"
19 #include "../preallocated_stack_allocator.hpp"
21 typedef preallocated_stack_allocator stack_allocator
;
22 typedef boost::coroutines::asymmetric_coroutine
< void > coro_type
;
24 boost::coroutines::flag_fpu_t preserve_fpu
= boost::coroutines::fpu_not_preserved
;
25 boost::coroutines::flag_unwind_t unwind_stack
= boost::coroutines::stack_unwind
;
26 boost::uint64_t jobs
= 1000;
28 void fn( coro_type::push_type
& c
)
29 { while ( true) c(); }
31 duration_type
measure_time( duration_type overhead
)
33 stack_allocator stack_alloc
;
35 time_point_type
start( clock_type::now() );
36 for ( std::size_t i
= 0; i
< jobs
; ++i
) {
37 coro_type::pull_type
c( fn
,
38 boost::coroutines::attributes( unwind_stack
, preserve_fpu
),
41 duration_type total
= clock_type::now() - start
;
42 total
-= overhead_clock(); // overhead of measurement
43 total
/= jobs
; // loops
48 # ifdef BOOST_CONTEXT_CYCLE
49 cycle_type
measure_cycles( cycle_type overhead
)
51 stack_allocator stack_alloc
;
53 cycle_type
start( cycles() );
54 for ( std::size_t i
= 0; i
< jobs
; ++i
) {
55 coro_type::pull_type
c( fn
,
56 boost::coroutines::attributes( unwind_stack
, preserve_fpu
),
59 cycle_type total
= cycles() - start
;
60 total
-= overhead
; // overhead of measurement
61 total
/= jobs
; // loops
67 int main( int argc
, char * argv
[])
71 bool preserve
= false, unwind
= true, bind
= false;
72 boost::program_options::options_description
desc("allowed options");
74 ("help", "help message")
75 ("bind,b", boost::program_options::value
< bool >( & bind
), "bind thread to CPU")
76 ("fpu,f", boost::program_options::value
< bool >( & preserve
), "preserve FPU registers")
77 ("unwind,u", boost::program_options::value
< bool >( & unwind
), "unwind coroutine-stack")
78 ("jobs,j", boost::program_options::value
< boost::uint64_t >( & jobs
), "jobs to run");
80 boost::program_options::variables_map vm
;
81 boost::program_options::store(
82 boost::program_options::parse_command_line(
87 boost::program_options::notify( vm
);
89 if ( vm
.count("help") ) {
90 std::cout
<< desc
<< std::endl
;
94 if ( preserve
) preserve_fpu
= boost::coroutines::fpu_preserved
;
95 if ( ! unwind
) unwind_stack
= boost::coroutines::no_stack_unwind
;
96 if ( bind
) bind_to_processor( 0);
98 duration_type overhead_c
= overhead_clock();
99 std::cout
<< "overhead " << overhead_c
.count() << " nano seconds" << std::endl
;
100 boost::uint64_t res
= measure_time( overhead_c
).count();
101 std::cout
<< "average of " << res
<< " nano seconds" << std::endl
;
102 #ifdef BOOST_CONTEXT_CYCLE
103 cycle_type overhead_y
= overhead_cycle();
104 std::cout
<< "overhead " << overhead_y
<< " cpu cycles" << std::endl
;
105 res
= measure_cycles( overhead_y
);
106 std::cout
<< "average of " << res
<< " cpu cycles" << std::endl
;
111 catch ( std::exception
const& e
)
112 { std::cerr
<< "exception: " << e
.what() << std::endl
; }
114 { std::cerr
<< "unhandled exception" << std::endl
; }