libcopp  2.2.0
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 
34 int switch_count = 100;
35 
36 typedef copp::coroutine_context_container<copp::allocator::stack_allocator_memory> my_cotoutine_t;
37 
38 // define a coroutine runner
39 static 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 
50 int MAX_COROUTINE_NUMBER = 100000; // 协程数量
51 my_cotoutine_t::ptr_t *co_arr = nullptr;
52 
53 // === 栈内存池 ===
54 char *stack_mem_pool = nullptr;
55 
56 int 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 = 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[MAX_COROUTINE_NUMBER * stack_size];
81  memset(stack_mem_pool, 0, 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[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 + 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 }
LIBCOPP_COPP_API coroutine_context * get_coroutine() LIBCOPP_MACRO_NOEXCEPT
get current coroutine
copp::coroutine_context_container< copp::allocator::stack_allocator_memory > my_cotoutine_t
int main(int argc, char *argv[])
static int my_runner(void *)
my_cotoutine_t::ptr_t * co_arr
#define CALC_NS_AVG_CLOCK(x, y)