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