libcopp 2.3.1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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// =============== 内存池对象 ===============
38struct stack_mem_pool_t {
39 int index;
40 char *buff;
41 stack_mem_pool_t() : index(0), buff(nullptr) {}
42};
43stack_mem_pool_t stack_mem_pool;
44// --------------- 内存池对象 ---------------
45
46int switch_count = 100;
47int max_task_number = 100000; // 协程Task数量
48size_t g_stack_size = 16 * 1024;
49
50struct 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
56typedef cotask::task<my_macro_coroutine> my_task_t;
57
58std::vector<my_task_t::ptr_t> task_arr;
59
60// define a coroutine runner
61int 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
72int 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 = static_cast<size_t>(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 * static_cast<size_t>(max_task_number)];
97 memset(stack_mem_pool.buff, 0, g_stack_size * static_cast<size_t>(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(
106 stack_mem_pool.buff + static_cast<size_t>(stack_mem_pool.index) * g_stack_size, 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[static_cast<size_t>(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[static_cast<size_t>(i)]->is_completed()) {
133 continue_flag = true;
134 ++real_switch_times;
135 task_arr[static_cast<size_t>(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
162int main() {
163 puts("cotask disabled.");
164 return 0;
165}
166
167#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()
cotask::task my_task_t