libcopp  1.1.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 
11 #include <cstdio>
12 #include <cstdlib>
13 #include <cstring>
14 #include <ctime>
15 #include <inttypes.h>
16 #include <stdint.h>
17 #include <vector>
18 
19 // include manager header file
20 #include <libcotask/task.h>
21 
22 #ifdef LIBCOTASK_MACRO_ENABLED
23 
24 #if defined(PROJECT_LIBCOPP_SAMPLE_HAS_CHRONO) && PROJECT_LIBCOPP_SAMPLE_HAS_CHRONO
25 #include <chrono>
26 #define CALC_CLOCK_T std::chrono::system_clock::time_point
27 #define CALC_CLOCK_NOW() std::chrono::system_clock::now()
28 #define CALC_MS_CLOCK(x) static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(x).count())
29 #define CALC_NS_AVG_CLOCK(x, y) 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(NULL) {}
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 stack_size = 16 * 1024;
49 
50 struct my_macro_coroutine {
51  typedef copp::allocator::stack_allocator_memory stack_allocator_t;
52 
54 };
55 
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 
65  while (count-- > 0)
67 
68  return 0;
69 }
70 
71 int main(int argc, char *argv[]) {
72  puts("###################### task (stack using memory pool) ###################");
73  printf("########## Cmd:");
74  for (int i = 0; i < argc; ++i) {
75  printf(" %s", argv[i]);
76  }
77  puts("");
78 
79  if (argc > 1) {
80  max_task_number = atoi(argv[1]);
81  }
82 
83  if (argc > 2) {
84  switch_count = atoi(argv[2]);
85  }
86 
87  if (argc > 3) {
88  stack_size = atoi(argv[3]) * 1024;
89  }
90 
91  stack_mem_pool.index = 0;
92  stack_mem_pool.buff = new char[stack_size * max_task_number];
93  memset(stack_mem_pool.buff, 0, stack_size * max_task_number);
94 
95  time_t begin_time = time(NULL);
96  CALC_CLOCK_T begin_clock = CALC_CLOCK_NOW();
97 
98  // create coroutines
99  task_arr.reserve(static_cast<size_t>(max_task_number));
100  while (task_arr.size() < static_cast<size_t>(max_task_number)) {
101  copp::allocator::stack_allocator_memory alloc(stack_mem_pool.buff + stack_mem_pool.index * stack_size, stack_size);
102  ++stack_mem_pool.index;
103  task_arr.push_back(my_task_t::create(my_task_action, alloc, stack_size));
104  }
105 
106  time_t end_time = time(NULL);
107  CALC_CLOCK_T end_clock = CALC_CLOCK_NOW();
108  printf("create %d task, cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number, static_cast<int>(end_time - begin_time),
109  CALC_MS_CLOCK(end_clock - begin_clock), CALC_NS_AVG_CLOCK(end_clock - begin_clock, max_task_number));
110 
111  begin_time = end_time;
112  begin_clock = end_clock;
113 
114  // start a task
115  for (int i = 0; i < max_task_number; ++i) {
116  task_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_task_number; ++i) {
126  if (false == task_arr[i]->is_completed()) {
127  continue_flag = true;
128  ++real_switch_times;
129  task_arr[i]->resume();
130  }
131  }
132  }
133 
134  end_time = time(NULL);
135  end_clock = CALC_CLOCK_NOW();
136  printf("switch %d tasks %lld times, cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number, real_switch_times,
137  static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
138  CALC_NS_AVG_CLOCK(end_clock - begin_clock, real_switch_times));
139 
140  begin_time = end_time;
141  begin_clock = end_clock;
142 
143  task_arr.clear();
144 
145  end_time = time(NULL);
146  end_clock = CALC_CLOCK_NOW();
147  printf("remove %d tasks, cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number, static_cast<int>(end_time - begin_time),
148  CALC_MS_CLOCK(end_clock - begin_clock), CALC_NS_AVG_CLOCK(end_clock - begin_clock, max_task_number));
149 
150  delete[] stack_mem_pool.buff;
151 
152  return 0;
153 }
154 #else
155 int main() {
156  puts("cotask disabled.");
157  return 0;
158 }
159 
160 #endif
#define CALC_MS_CLOCK(x)
memory allocator this allocator will return address of specified memory section
cotask::task my_task_t
static ptr_t create(const Ty &functor, size_t stack_size=0, size_t private_buffer_size=0)
create task with functor
Definition: task.h:155
#define CALC_CLOCK_NOW()
coroutine container contain stack context, stack allocator and runtime fcontext
impl::task_impl * get_task() UTIL_CONFIG_NOEXCEPT
get current running task
Definition: this_task.cpp:15
#define CALC_CLOCK_T
virtual int yield(void **priv_data)=0
#define CALC_NS_AVG_CLOCK(x, y)