libcopp 2.3.1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sample_benchmark_task_stack_pool.cpp
Go to the documentation of this file.
1/*
2 * sample_benchmark_task_stack_pool.cpp
3 *
4 * Created on: 2017年5月19日
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
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) \
30 static_cast<long long>(std::chrono::duration_cast<std::chrono::nanoseconds>(x).count() / (y ? y : 1))
31# else
32# define CALC_CLOCK_T clock_t
33# define CALC_CLOCK_NOW() clock()
34# define CALC_MS_CLOCK(x) static_cast<int>((x) / (CLOCKS_PER_SEC / 1000))
35# define CALC_NS_AVG_CLOCK(x, y) (1000000LL * static_cast<long long>((x) / (CLOCKS_PER_SEC / 1000)) / (y ? y : 1))
36# endif
37
38// =============== 栈池对象 ===============
39typedef copp::stack_pool<copp::allocator::default_statck_allocator> stack_pool_t;
40stack_pool_t::ptr_t global_stack_pool;
41// --------------- 栈池对象 ---------------
42
43int switch_count = 100;
44int max_task_number = 100000; // 协程Task数量
45
46struct my_macro_coroutine {
47 using stack_allocator_type = copp::allocator::stack_allocator_pool<stack_pool_t>;
48 using coroutine_type = copp::coroutine_context_container<stack_allocator_type>;
49 using value_type = int;
50};
51
52typedef cotask::task<my_macro_coroutine> my_task_t;
53
54std::vector<my_task_t::ptr_t> task_arr;
55
56// define a coroutine runner
57int my_task_action(void *) {
58 // ... your code here ...
59 int count = switch_count; // 每个task地切换次数
60 cotask::impl::task_impl *self = cotask::this_task::get_task();
61 while (count-- > 0) {
62 self->yield();
63 }
64
65 return 0;
66}
67
68static void benchmark_round(int index) {
69 printf("### Round: %d ###\n", index);
70
71 time_t begin_time = time(nullptr);
72 CALC_CLOCK_T begin_clock = CALC_CLOCK_NOW();
73
74 // create coroutines
75 task_arr.reserve(static_cast<size_t>(max_task_number));
76 while (task_arr.size() < static_cast<size_t>(max_task_number)) {
77 copp::allocator::stack_allocator_pool<stack_pool_t> alloc(global_stack_pool);
78 my_task_t::ptr_t new_task = my_task_t::create(my_task_action, alloc, 0);
79 if (!new_task) {
80 fprintf(stderr, "create coroutine task failed, real size is %d.\n", static_cast<int>(task_arr.size()));
81 fprintf(stderr, "maybe sysconf [vm.max_map_count] extended.\n");
82 max_task_number = static_cast<int>(task_arr.size());
83 break;
84 } else {
85 task_arr.push_back(new_task);
86 }
87 }
88
89 time_t end_time = time(nullptr);
90 CALC_CLOCK_T end_clock = CALC_CLOCK_NOW();
91 printf("create %d task, cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number,
92 static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
93 CALC_NS_AVG_CLOCK(end_clock - begin_clock, max_task_number));
94
95 begin_time = end_time;
96 begin_clock = end_clock;
97
98 // start a task
99 for (int i = 0; i < max_task_number; ++i) {
100 task_arr[static_cast<size_t>(i)]->start();
101 }
102
103 // yield & resume from runner
104 bool continue_flag = true;
105 long long real_switch_times = static_cast<long long>(0);
106
107 while (continue_flag) {
108 continue_flag = false;
109 for (int i = 0; i < max_task_number; ++i) {
110 if (false == task_arr[static_cast<size_t>(i)]->is_completed()) {
111 continue_flag = true;
112 ++real_switch_times;
113 task_arr[static_cast<size_t>(i)]->resume();
114 }
115 }
116 }
117
118 end_time = time(nullptr);
119 end_clock = CALC_CLOCK_NOW();
120 printf("switch %d tasks %lld times, cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number,
121 real_switch_times, static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
122 CALC_NS_AVG_CLOCK(end_clock - begin_clock, real_switch_times));
123
124 begin_time = end_time;
125 begin_clock = end_clock;
126
127 task_arr.clear();
128
129 end_time = time(nullptr);
130 end_clock = CALC_CLOCK_NOW();
131 printf("remove %d tasks, cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number,
132 static_cast<int>(end_time - begin_time), CALC_MS_CLOCK(end_clock - begin_clock),
133 CALC_NS_AVG_CLOCK(end_clock - begin_clock, max_task_number));
134}
135
136int main(int argc, char *argv[]) {
137 puts("###################### task (stack using stack pool) ###################");
138 printf("########## Cmd:");
139 for (int i = 0; i < argc; ++i) {
140 printf(" %s", argv[i]);
141 }
142 puts("");
143
144 if (argc > 1) {
145 max_task_number = atoi(argv[1]);
146 }
147
148 if (argc > 2) {
149 switch_count = atoi(argv[2]);
150 }
151
152 size_t stack_size = 16 * 1024;
153 if (argc > 3) {
154 stack_size = static_cast<size_t>(atoi(argv[3]) * 1024);
155 }
156
157 global_stack_pool = stack_pool_t::create();
158 global_stack_pool->set_min_stack_number(static_cast<size_t>(max_task_number));
159 global_stack_pool->set_stack_size(stack_size);
160
161 for (int i = 1; i <= 5; ++i) {
163 }
164 return 0;
165}
166#else
167int main() {
168 puts("cotask disabled.");
169 return 0;
170}
171
172#endif
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()
static void benchmark_round(int index)
stack_pool_t::ptr_t global_stack_pool
copp::stack_pool< copp::allocator::default_statck_allocator > stack_pool_t
cotask::task my_task_t