libcopp  2.2.0
sample_benchmark_task.cpp
Go to the documentation of this file.
1 /*
2  * sample_stress_test_task.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 typedef cotask::task<> my_task_t;
38 
39 int switch_count = 100;
40 int max_task_number = 100000; // 协程Task数量
41 std::vector<my_task_t::ptr_t> task_arr;
42 
43 // define a coroutine runner
44 static int my_task_action(void *) {
45  // ... your code here ...
46  int count = switch_count; // 每个task地切换次数
47  cotask::impl::task_impl *self = cotask::this_task::get_task();
48  while (count-- > 0) {
49  self->yield();
50  }
51 
52  return 0;
53 }
54 
55 int main(int argc, char *argv[]) {
56 # ifdef LIBCOPP_MACRO_SYS_POSIX
57  puts("###################### context coroutine (stack using default allocator[mmap]) ###################");
58 # elif defined(LIBCOPP_MACRO_SYS_WIN)
59  puts("###################### context coroutine (stack using default allocator[VirtualAlloc]) ###################");
60 # else
61  puts("###################### context coroutine (stack using default allocator ###################");
62 # endif
63  printf("########## Cmd:");
64  for (int i = 0; i < argc; ++i) {
65  printf(" %s", argv[i]);
66  }
67  puts("");
68 
69  if (argc > 1) {
70  max_task_number = atoi(argv[1]);
71  }
72 
73  if (argc > 2) {
74  switch_count = atoi(argv[2]);
75  }
76 
77  size_t stack_size = 16 * 1024;
78  if (argc > 3) {
79  stack_size = atoi(argv[3]) * 1024;
80  }
81 
82  time_t begin_time = time(nullptr);
83  CALC_CLOCK_T begin_clock = CALC_CLOCK_NOW();
84 
85  // create coroutines
86  task_arr.reserve(static_cast<size_t>(max_task_number));
87  while (task_arr.size() < static_cast<size_t>(max_task_number)) {
88  my_task_t::ptr_t new_task = my_task_t::create(my_task_action, stack_size);
89  if (!new_task) {
90  fprintf(stderr, "create coroutine task failed, real size is %d.\n", static_cast<int>(task_arr.size()));
91  fprintf(stderr, "maybe sysconf [vm.max_map_count] extended.\n");
92  max_task_number = static_cast<int>(task_arr.size());
93  break;
94  }
95  task_arr.push_back(new_task);
96  }
97 
98  time_t end_time = time(nullptr);
99  CALC_CLOCK_T end_clock = CALC_CLOCK_NOW();
100  printf("create %d task, cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number,
101  static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
102  CALC_NS_AVG_CLOCK(end_clock - begin_clock, max_task_number));
103 
104  begin_time = end_time;
105  begin_clock = end_clock;
106 
107  // start a task
108  for (int i = 0; i < max_task_number; ++i) {
109  task_arr[i]->start();
110  }
111 
112  // yield & resume from runner
113  bool continue_flag = true;
114  long long real_switch_times = static_cast<long long>(0);
115 
116  while (continue_flag) {
117  continue_flag = false;
118  for (int i = 0; i < max_task_number; ++i) {
119  if (false == task_arr[i]->is_completed()) {
120  continue_flag = true;
121  ++real_switch_times;
122  task_arr[i]->resume();
123  }
124  }
125  }
126 
127  end_time = time(nullptr);
128  end_clock = CALC_CLOCK_NOW();
129  printf("switch %d tasks %lld times, cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number,
130  real_switch_times, static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
131  CALC_NS_AVG_CLOCK(end_clock - begin_clock, real_switch_times));
132 
133  begin_time = end_time;
134  begin_clock = end_clock;
135 
136  task_arr.clear();
137 
138  end_time = time(nullptr);
139  end_clock = CALC_CLOCK_NOW();
140  printf("remove %d tasks, cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number,
141  static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
142  CALC_NS_AVG_CLOCK(end_clock - begin_clock, max_task_number));
143 
144  return 0;
145 }
146 #else
147 int main() {
148  puts("cotask disabled");
149  return 0;
150 }
151 #endif
LIBCOPP_COTASK_API impl::task_impl * get_task() LIBCOPP_MACRO_NOEXCEPT
get current running task
Definition: this_task.cpp:9
#define CALC_CLOCK_T
#define CALC_MS_CLOCK(x)
#define CALC_NS_AVG_CLOCK(x, y)
#define CALC_CLOCK_NOW()
int main()
cotask::task my_task_t