libcopp  1.1.0
sample_benchmark_coroutine_malloc.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 
11 #include <cstdio>
12 #include <cstdlib>
13 #include <cstring>
14 #include <ctime>
15 #include <inttypes.h>
16 #include <stdint.h>
17 
18 // 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) 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 
37 
38 // define a coroutine runner
39 static int my_runner(void *) {
40  // ... your code here ...
41  int count = switch_count; // 每个协程N次切换
42  my_cotoutine_t *addr = copp::this_coroutine::get<my_cotoutine_t>();
43 
44  while (count-- > 0) {
45  addr->yield();
46  }
47 
48  return 1;
49 }
50 
51 int MAX_COROUTINE_NUMBER = 100000; // 协程数量
53 
54 int main(int argc, char *argv[]) {
55  puts("###################### context coroutine (stack using malloc/free) ###################");
56  printf("########## Cmd:");
57  for (int i = 0; i < argc; ++i) {
58  printf(" %s", argv[i]);
59  }
60  puts("");
61 
62  if (argc > 1) {
63  MAX_COROUTINE_NUMBER = atoi(argv[1]);
64  }
65 
66  if (argc > 2) {
67  switch_count = atoi(argv[2]);
68  }
69 
70  size_t stack_size = 16 * 1024;
71  if (argc > 3) {
72  stack_size = atoi(argv[3]) * 1024;
73  }
74 
75  time_t begin_time = time(NULL);
76  CALC_CLOCK_T begin_clock = CALC_CLOCK_NOW();
77 
78  // create coroutines
80 
81  time_t end_time = time(NULL);
82  CALC_CLOCK_T end_clock = CALC_CLOCK_NOW();
83  printf("allocate %d coroutine, cost time: %d s, clock time: %d ms, avg: %lld ns\n", MAX_COROUTINE_NUMBER,
84  static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
85  CALC_NS_AVG_CLOCK(end_clock - begin_clock, MAX_COROUTINE_NUMBER));
86 
87  // create a runner
88  // bind runner to coroutine object
89  for (int i = 0; i < MAX_COROUTINE_NUMBER; ++i) {
90  co_arr[i] = my_cotoutine_t::create(my_runner, stack_size);
91  }
92 
93  end_time = time(NULL);
94  end_clock = CALC_CLOCK_NOW();
95  printf("create %d coroutine, cost time: %d s, clock time: %d ms, avg: %lld ns\n", MAX_COROUTINE_NUMBER,
96  static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
97  CALC_NS_AVG_CLOCK(end_clock - begin_clock, MAX_COROUTINE_NUMBER));
98 
99  begin_time = end_time;
100  begin_clock = end_clock;
101 
102  // start a coroutine
103  for (int i = 0; i < MAX_COROUTINE_NUMBER; ++i) {
104  co_arr[i]->start();
105  }
106 
107  // yield & resume from runner
108  bool continue_flag = true;
109  long long real_switch_times = static_cast<long long>(0);
110 
111  while (continue_flag) {
112  continue_flag = false;
113  for (int i = 0; i < MAX_COROUTINE_NUMBER; ++i) {
114  if (false == co_arr[i]->is_finished()) {
115  continue_flag = true;
116  ++real_switch_times;
117  co_arr[i]->resume();
118  }
119  }
120  }
121 
122  end_time = time(NULL);
123  end_clock = CALC_CLOCK_NOW();
124  printf("switch %d coroutine contest %lld times, cost time: %d s, clock time: %d ms, avg: %lld ns\n", MAX_COROUTINE_NUMBER,
125  real_switch_times, static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
126  CALC_NS_AVG_CLOCK(end_clock - begin_clock, real_switch_times));
127 
128  begin_time = end_time;
129  begin_clock = end_clock;
130 
131  delete[] co_arr;
132 
133  end_time = time(NULL);
134  end_clock = CALC_CLOCK_NOW();
135  printf("remove %d coroutine, cost time: %d s, clock time: %d ms, avg: %lld ns\n", MAX_COROUTINE_NUMBER,
136  static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
137  CALC_NS_AVG_CLOCK(end_clock - begin_clock, MAX_COROUTINE_NUMBER));
138 
139  return 0;
140 }
static int my_runner(void *)
#define CALC_NS_AVG_CLOCK(x, y)
copp::coroutine_context_container< copp::allocator::stack_allocator_malloc > my_cotoutine_t
static ptr_t create(const callback_t &runner, allocator_type &alloc, size_t stack_sz=0, size_t private_buffer_size=0, size_t coroutine_size=0) UTIL_CONFIG_NOEXCEPT
create and init coroutine with specify runner and specify stack size
my_cotoutine_t::ptr_t * co_arr
int main(int argc, char *argv[])
#define CALC_CLOCK_NOW()
int yield(void **priv_data=UTIL_CONFIG_NULLPTR)
yield coroutine
coroutine container contain stack context, stack allocator and runtime fcontext
#define CALC_MS_CLOCK(x)