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