libcopp  2.2.0
sample_benchmark_task_mem_pool.cpp
Go to the documentation of this file.
1 /*
2  * sample_stress_test_task_mem_pool.cpp
3  *
4  * Created on: 2014年5月11日
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 #include <vector>
17 
18 // include manager header file
19 #include <libcotask/task.h>
20 
21 #ifdef LIBCOTASK_MACRO_ENABLED
22 
23 # if defined(PROJECT_LIBCOPP_SAMPLE_HAS_CHRONO) && PROJECT_LIBCOPP_SAMPLE_HAS_CHRONO
24 # include <chrono>
25 # define CALC_CLOCK_T std::chrono::system_clock::time_point
26 # define CALC_CLOCK_NOW() std::chrono::system_clock::now()
27 # define CALC_MS_CLOCK(x) static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(x).count())
28 # define CALC_NS_AVG_CLOCK(x, y) \
29  static_cast<long long>(std::chrono::duration_cast<std::chrono::nanoseconds>(x).count() / (y ? y : 1))
30 # else
31 # define CALC_CLOCK_T clock_t
32 # define CALC_CLOCK_NOW() clock()
33 # define CALC_MS_CLOCK(x) static_cast<int>((x) / (CLOCKS_PER_SEC / 1000))
34 # define CALC_NS_AVG_CLOCK(x, y) (1000000LL * static_cast<long long>((x) / (CLOCKS_PER_SEC / 1000)) / (y ? y : 1))
35 # endif
36 
37 // =============== 内存池对象 ===============
38 struct stack_mem_pool_t {
39  int index;
40  char *buff;
41  stack_mem_pool_t() : index(0), buff(nullptr) {}
42 };
43 stack_mem_pool_t stack_mem_pool;
44 // --------------- 内存池对象 ---------------
45 
46 int switch_count = 100;
47 int max_task_number = 100000; // 协程Task数量
48 size_t g_stack_size = 16 * 1024;
49 
50 struct my_macro_coroutine {
51  using stack_allocator_type = copp::allocator::stack_allocator_memory;
52  using coroutine_type = copp::coroutine_context_container<stack_allocator_type>;
53  using value_type = int;
54 };
55 
56 typedef cotask::task<my_macro_coroutine> my_task_t;
57 
58 std::vector<my_task_t::ptr_t> task_arr;
59 
60 // define a coroutine runner
61 int my_task_action(void *) {
62  // ... your code here ...
63  int count = switch_count; // 每个task地切换次数
64  cotask::impl::task_impl *self = cotask::this_task::get_task();
65  while (count-- > 0) {
66  self->yield();
67  }
68 
69  return 0;
70 }
71 
72 int main(int argc, char *argv[]) {
73  puts("###################### task (stack using memory pool) ###################");
74  printf("########## Cmd:");
75  for (int i = 0; i < argc; ++i) {
76  printf(" %s", argv[i]);
77  }
78  puts("");
79 
80  if (argc > 1) {
81  max_task_number = atoi(argv[1]);
82  }
83 
84  if (argc > 2) {
85  switch_count = atoi(argv[2]);
86  }
87 
88  if (argc > 3) {
89  g_stack_size = atoi(argv[3]) * 1024;
90  }
91  if (g_stack_size < copp::stack_traits::minimum_size()) {
92  g_stack_size = copp::stack_traits::minimum_size();
93  }
94 
95  stack_mem_pool.index = 0;
96  stack_mem_pool.buff = new char[g_stack_size * max_task_number];
97  memset(stack_mem_pool.buff, 0, g_stack_size * max_task_number);
98 
99  time_t begin_time = time(nullptr);
100  CALC_CLOCK_T begin_clock = CALC_CLOCK_NOW();
101 
102  // create coroutines
103  task_arr.reserve(static_cast<size_t>(max_task_number));
104  while (task_arr.size() < static_cast<size_t>(max_task_number)) {
105  copp::allocator::stack_allocator_memory alloc(stack_mem_pool.buff + stack_mem_pool.index * g_stack_size,
106  g_stack_size);
107  ++stack_mem_pool.index;
108  task_arr.push_back(my_task_t::create(my_task_action, alloc, g_stack_size));
109  }
110 
111  time_t end_time = time(nullptr);
112  CALC_CLOCK_T end_clock = CALC_CLOCK_NOW();
113  printf("create %d task, cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number,
114  static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
115  CALC_NS_AVG_CLOCK(end_clock - begin_clock, max_task_number));
116 
117  begin_time = end_time;
118  begin_clock = end_clock;
119 
120  // start a task
121  for (int i = 0; i < max_task_number; ++i) {
122  task_arr[i]->start();
123  }
124 
125  // yield & resume from runner
126  bool continue_flag = true;
127  long long real_switch_times = static_cast<long long>(0);
128 
129  while (continue_flag) {
130  continue_flag = false;
131  for (int i = 0; i < max_task_number; ++i) {
132  if (false == task_arr[i]->is_completed()) {
133  continue_flag = true;
134  ++real_switch_times;
135  task_arr[i]->resume();
136  }
137  }
138  }
139 
140  end_time = time(nullptr);
141  end_clock = CALC_CLOCK_NOW();
142  printf("switch %d tasks %lld times, cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number,
143  real_switch_times, static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
144  CALC_NS_AVG_CLOCK(end_clock - begin_clock, real_switch_times));
145 
146  begin_time = end_time;
147  begin_clock = end_clock;
148 
149  task_arr.clear();
150 
151  end_time = time(nullptr);
152  end_clock = CALC_CLOCK_NOW();
153  printf("remove %d tasks, cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number,
154  static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
155  CALC_NS_AVG_CLOCK(end_clock - begin_clock, max_task_number));
156 
157  delete[] stack_mem_pool.buff;
158 
159  return 0;
160 }
161 #else
162 int main() {
163  puts("cotask disabled.");
164  return 0;
165 }
166 
167 #endif
LIBCOPP_COTASK_API impl::task_impl * get_task() LIBCOPP_MACRO_NOEXCEPT
get current running task
Definition: this_task.cpp:9
std::shared_ptr< cli::cmd_option_value > value_type
Definition: cmd_option.h:50
#define CALC_CLOCK_T
#define CALC_MS_CLOCK(x)
#define CALC_NS_AVG_CLOCK(x, y)
#define CALC_CLOCK_NOW()
cotask::task my_task_t