libcopp 2.3.1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sample_benchmark_coroutine_stack_pool.cpp
Go to the documentation of this file.
1/*
2 * sample_benchmark_coroutine_stack_pool.cpp
3 *
4 * Created on: 2017年5月09日
5 * Author: owent
6 *
7 * Released under the MIT license
8 */
9
10#include <inttypes.h>
11#include <stdint.h>
12#include <cstdio>
13#include <cstdlib>
14#include <cstring>
15#include <ctime>
16
17// include manager header file
20
21#if defined(PROJECT_LIBCOPP_SAMPLE_HAS_CHRONO) && PROJECT_LIBCOPP_SAMPLE_HAS_CHRONO
22# include <chrono>
23# define CALC_CLOCK_T std::chrono::system_clock::time_point
24# define CALC_CLOCK_NOW() std::chrono::system_clock::now()
25# define CALC_MS_CLOCK(x) static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(x).count())
26# define CALC_NS_AVG_CLOCK(x, y) \
27 static_cast<long long>(std::chrono::duration_cast<std::chrono::nanoseconds>(x).count() / (y ? y : 1))
28#else
29# define CALC_CLOCK_T clock_t
30# define CALC_CLOCK_NOW() clock()
31# define CALC_MS_CLOCK(x) static_cast<int>((x) / (CLOCKS_PER_SEC / 1000))
32# define CALC_NS_AVG_CLOCK(x, y) (1000000LL * static_cast<long long>((x) / (CLOCKS_PER_SEC / 1000)) / (y ? y : 1))
33#endif
34
35// === 栈内存池 ===
36typedef copp::stack_pool<copp::allocator::default_statck_allocator> stack_pool_t;
37stack_pool_t::ptr_t global_stack_pool;
38int switch_count = 100;
39
40typedef copp::coroutine_context_container<copp::allocator::stack_allocator_pool<stack_pool_t> > my_cotoutine_t;
41
42// define a coroutine runner
43static int my_runner(void *) {
44 // ... your code here ...
45 int count = switch_count; // 每个协程N次切换
46 copp::coroutine_context *self = copp::this_coroutine::get_coroutine();
47 while (count-- > 0) {
48 self->yield();
49 }
50
51 return 1;
52}
53
54int MAX_COROUTINE_NUMBER = 100000; // 协程数量
55
56static void benchmark_round(int index) {
57 printf("### Round: %d ###\n", index);
58
59 time_t begin_time = time(nullptr);
60 CALC_CLOCK_T begin_clock = CALC_CLOCK_NOW();
61
62 // create coroutines
63 my_cotoutine_t::ptr_t *co_arr = new my_cotoutine_t::ptr_t[static_cast<size_t>(MAX_COROUTINE_NUMBER)];
64
65 time_t end_time = time(nullptr);
66 CALC_CLOCK_T end_clock = CALC_CLOCK_NOW();
67 printf("allocate %d coroutine, cost time: %d s, clock time: %d ms, avg: %lld ns\n", MAX_COROUTINE_NUMBER,
68 static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
69 CALC_NS_AVG_CLOCK(end_clock - begin_clock, MAX_COROUTINE_NUMBER));
70
71 for (int i = 0; i < MAX_COROUTINE_NUMBER; ++i) {
72 copp::allocator::stack_allocator_pool<stack_pool_t> alloc(global_stack_pool);
73 co_arr[i] = my_cotoutine_t::create(my_runner, alloc);
74 if (!co_arr[i]) {
75 fprintf(stderr, "coroutine create failed, the real number is %d\n", i);
76 fprintf(stderr, "maybe sysconf [vm.max_map_count] extended?\n");
78 break;
79 }
80 }
81
82 end_time = time(nullptr);
83 end_clock = CALC_CLOCK_NOW();
84 printf("create %d coroutine, cost time: %d s, clock time: %d ms, avg: %lld ns\n", MAX_COROUTINE_NUMBER,
85 static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
86 CALC_NS_AVG_CLOCK(end_clock - begin_clock, MAX_COROUTINE_NUMBER));
87
88 begin_time = end_time;
89 begin_clock = end_clock;
90
91 // start a coroutine
92 for (int i = 0; i < MAX_COROUTINE_NUMBER; ++i) {
93 co_arr[i]->start();
94 }
95
96 // yield & resume from runner
97 bool continue_flag = true;
98 long long real_switch_times = static_cast<long long>(0);
99
100 while (continue_flag) {
101 continue_flag = false;
102 for (int i = 0; i < MAX_COROUTINE_NUMBER; ++i) {
103 if (0 == co_arr[i]->resume()) {
104 continue_flag = true;
105 ++real_switch_times;
106 }
107 }
108 }
109
110 end_time = time(nullptr);
111 end_clock = CALC_CLOCK_NOW();
112 printf("switch %d coroutine contest %lld times, cost time: %d s, clock time: %d ms, avg: %lld ns\n",
113 MAX_COROUTINE_NUMBER, real_switch_times, static_cast<int>(end_time - begin_time),
114 CALC_MS_CLOCK(end_clock - begin_clock), CALC_NS_AVG_CLOCK(end_clock - begin_clock, real_switch_times));
115
116 begin_time = end_time;
117 begin_clock = end_clock;
118
119 delete[] co_arr;
120
121 end_time = time(nullptr);
122 end_clock = CALC_CLOCK_NOW();
123 printf("remove %d coroutine, cost time: %d s, clock time: %d ms, avg: %lld ns\n", MAX_COROUTINE_NUMBER,
124 static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
125 CALC_NS_AVG_CLOCK(end_clock - begin_clock, MAX_COROUTINE_NUMBER));
126}
127
128int main(int argc, char *argv[]) {
129 puts("###################### context coroutine (stack using stack pool) ###################");
130 printf("########## Cmd:");
131 for (int i = 0; i < argc; ++i) {
132 printf(" %s", argv[i]);
133 }
134 puts("");
135
136 if (argc > 1) {
137 MAX_COROUTINE_NUMBER = atoi(argv[1]);
138 }
139
140 if (argc > 2) {
141 switch_count = atoi(argv[2]);
142 }
143
144 size_t stack_size = 16 * 1024;
145 if (argc > 3) {
146 stack_size = static_cast<size_t>(atoi(argv[3]) * 1024);
147 }
148
149 global_stack_pool = stack_pool_t::create();
150 global_stack_pool->set_min_stack_number(static_cast<size_t>(MAX_COROUTINE_NUMBER));
151 global_stack_pool->set_stack_size(stack_size);
152
153 for (int i = 1; i <= 5; ++i) {
155 }
156 return 0;
157}
int main()
copp::coroutine_context_default::ptr_t * co_arr
static void benchmark_round(int index)
stack_pool_t::ptr_t global_stack_pool
copp::stack_pool< copp::allocator::default_statck_allocator > stack_pool_t
#define CALC_NS_AVG_CLOCK(x, y)
copp::coroutine_context_container< copp::allocator::stack_allocator_pool< stack_pool_t > > my_cotoutine_t