]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/fiber/performance/fiber/skynet_shared_detach.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / fiber / performance / fiber / skynet_shared_detach.cpp
CommitLineData
7c673cae
FG
1
2// Copyright Oliver Kowalke 2015.
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
b32b8144
FG
7// based on https://github.com/atemerev/skynet from Alexander Temerev
8
7c673cae
FG
9#include <algorithm>
10#include <cassert>
11#include <chrono>
b32b8144 12#include <cmath>
7c673cae
FG
13#include <condition_variable>
14#include <cstddef>
15#include <cstdint>
16#include <cstdlib>
17#include <deque>
18#include <iostream>
19#include <memory>
20#include <mutex>
21#include <numeric>
22#include <vector>
23
24#include <boost/fiber/all.hpp>
92f5a8d4 25#include <boost/fiber/numa/pin_thread.hpp>
b32b8144 26#include <boost/predef.h>
7c673cae
FG
27
28#include "barrier.hpp"
7c673cae
FG
29
30using allocator_type = boost::fibers::fixedsize_stack;
b32b8144 31using channel_type = boost::fibers::buffered_channel< std::uint64_t >;
7c673cae
FG
32using clock_type = std::chrono::steady_clock;
33using duration_type = clock_type::duration;
34using lock_type = std::unique_lock< std::mutex >;
35using time_point_type = clock_type::time_point;
36
37static bool done = false;
38static std::mutex mtx{};
39static boost::fibers::condition_variable_any cnd{};
40
41// microbenchmark
42void skynet( allocator_type & salloc, channel_type & c, std::size_t num, std::size_t size, std::size_t div) {
43 if ( 1 == size) {
44 c.push( num);
45 } else {
b32b8144 46 channel_type rc{ 16 };
7c673cae
FG
47 for ( std::size_t i = 0; i < div; ++i) {
48 auto sub_num = num + i * size / div;
49 boost::fibers::fiber{ boost::fibers::launch::dispatch,
b32b8144
FG
50 std::allocator_arg, salloc,
51 skynet,
52 std::ref( salloc), std::ref( rc), sub_num, size / div, div }.detach();
7c673cae
FG
53 }
54 std::uint64_t sum{ 0 };
55 for ( std::size_t i = 0; i < div; ++i) {
56 sum += rc.value_pop();
57 }
58 c.push( sum);
59 }
60}
61
b32b8144
FG
62void thread( unsigned int idx, barrier * b) {
63 boost::fibers::numa::pin_thread( idx);
7c673cae
FG
64 boost::fibers::use_scheduling_algorithm< boost::fibers::algo::shared_work >();
65 b->wait();
66 lock_type lk( mtx);
67 cnd.wait( lk, [](){ return done; });
68 BOOST_ASSERT( done);
69}
70
71int main() {
72 try {
73 boost::fibers::use_scheduling_algorithm< boost::fibers::algo::shared_work >();
74 unsigned int n = std::thread::hardware_concurrency();
75 barrier b( n);
b32b8144
FG
76 boost::fibers::numa::pin_thread( n - 1);
77 std::size_t size{ 1000000 };
7c673cae
FG
78 std::size_t div{ 10 };
79 std::vector< std::thread > threads;
80 for ( unsigned int i = 1; i < n; ++i) {
b32b8144 81 threads.emplace_back( thread, i - 1, & b);
7c673cae 82 };
b32b8144 83 allocator_type salloc{ 2*allocator_type::traits_type::page_size() };
7c673cae 84 std::uint64_t result{ 0 };
b32b8144 85 channel_type rc{ 2 };
7c673cae
FG
86 b.wait();
87 time_point_type start{ clock_type::now() };
88 skynet( salloc, rc, 0, size, div);
89 result = rc.value_pop();
b32b8144
FG
90 if ( 499999500000 != result) {
91 throw std::runtime_error("invalid result");
92 }
93 auto duration = clock_type::now() - start;
7c673cae
FG
94 lock_type lk( mtx);
95 done = true;
96 lk.unlock();
97 cnd.notify_all();
98 for ( std::thread & t : threads) {
99 t.join();
100 }
b32b8144 101 std::cout << "duration: " << duration.count() / 1000000 << " ms" << std::endl;
7c673cae
FG
102 return EXIT_SUCCESS;
103 } catch ( std::exception const& e) {
104 std::cerr << "exception: " << e.what() << std::endl;
105 } catch (...) {
106 std::cerr << "unhandled exception" << std::endl;
107 }
108 return EXIT_FAILURE;
109}