libcopp 2.3.1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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
37typedef cotask::task<> my_task_t;
38
39int switch_count = 100;
40int max_task_number = 100000; // 协程Task数量
41std::vector<my_task_t::ptr_t> task_arr;
42
43// define a coroutine runner
44static 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
55int 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 = static_cast<size_t>(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[static_cast<size_t>(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[static_cast<size_t>(i)]->is_completed()) {
120 continue_flag = true;
121 ++real_switch_times;
122 task_arr[static_cast<size_t>(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
147int main() {
148 puts("cotask disabled");
149 return 0;
150}
151#endif
#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