1 
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)
6 
7 #include <cstddef>
8 #include <cstdlib>
9 #include <iostream>
10 #include <stdexcept>
11 
12 #include <windows.h>
13 
14 #include <boost/chrono.hpp>
15 #include <boost/cstdint.hpp>
16 #include <boost/program_options.hpp>
17 
18 #include "../bind_processor.hpp"
19 #include "../clock.hpp"
20 #include "../cycle.hpp"
21 #include "../../example/simple_stack_allocator.hpp"
22 
23 typedef boost::context::simple_stack_allocator<
24             8 * 1024 * 1024, 64 * 1024, 8 * 1024
25         >                                       stack_allocator;
26 
27 boost::uint64_t jobs = 1000;
28 LPVOID fc, fm;
29 
fn(LPVOID)30 VOID __stdcall fn( LPVOID)
31 { while ( true) ::SwitchToFiber( fm); }
32 
measure_time()33 duration_type measure_time()
34 {
35     // cache warum-up
36     ::SwitchToFiber( fc);
37 
38     time_point_type start( clock_type::now() );
39     for ( std::size_t i = 0; i < jobs; ++i) {
40         ::SwitchToFiber( fc);
41     }
42     duration_type total = clock_type::now() - start;
43     total -= overhead_clock(); // overhead of measurement
44     total /= jobs;  // loops
45     total /= 2;  // 2x jump_fcontext
46 
47     return total;
48 }
49 
50 #ifdef BOOST_CONTEXT_CYCLE
measure_cycles()51 cycle_type measure_cycles()
52 {
53     // cache warum-up
54     ::SwitchToFiber( fc);
55 
56     cycle_type start( cycles() );
57     for ( std::size_t i = 0; i < jobs; ++i) {
58         ::SwitchToFiber( fc);
59     }
60     cycle_type total = cycles() - start;
61     total -= overhead_cycle(); // overhead of measurement
62     total /= jobs;  // loops
63     total /= 2;  // 2x jump_fcontext
64 
65     return total;
66 }
67 #endif
68 
main(int argc,char * argv[])69 int main( int argc, char * argv[])
70 {
71     try
72     {
73         bind_to_processor( 0);
74 
75         boost::program_options::options_description desc("allowed options");
76         desc.add_options()
77             ("help", "help message")
78             ("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
79 
80         boost::program_options::variables_map vm;
81         boost::program_options::store(
82                 boost::program_options::parse_command_line(
83                     argc,
84                     argv,
85                     desc),
86                 vm);
87         boost::program_options::notify( vm);
88 
89         if ( vm.count("help") ) {
90             std::cout << desc << std::endl;
91             return EXIT_SUCCESS;
92         }
93 
94         fm = ::ConvertThreadToFiber( 0);
95         fc = ::CreateFiber( stack_allocator::default_stacksize(), fn, 0);
96 
97         boost::uint64_t res = measure_time().count();
98         std::cout << "average of " << res << " nano seconds" << std::endl;
99 #ifdef BOOST_CONTEXT_CYCLE
100         res = measure_cycles();
101         std::cout << "average of " << res << " cpu cycles" << std::endl;
102 #endif
103 
104         return EXIT_SUCCESS;
105     }
106     catch ( std::exception const& e)
107     { std::cerr << "exception: " << e.what() << std::endl; }
108     catch (...)
109     { std::cerr << "unhandled exception" << std::endl; }
110     return EXIT_FAILURE;
111 }
112