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