16 #if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
18 # ifdef LIBCOTASK_MACRO_ENABLED
20 # if defined(PROJECT_LIBCOPP_SAMPLE_HAS_CHRONO) && PROJECT_LIBCOPP_SAMPLE_HAS_CHRONO
22 # define CALC_CLOCK_T std::chrono::system_clock::time_point
23 # define CALC_CLOCK_NOW() std::chrono::system_clock::now()
24 # define CALC_MS_CLOCK(x) static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(x).count())
25 # define CALC_NS_AVG_CLOCK(x, y) \
26 static_cast<long long>(std::chrono::duration_cast<std::chrono::nanoseconds>(x).count() / (y ? y : 1))
28 # define CALC_CLOCK_T clock_t
29 # define CALC_CLOCK_NOW() clock()
30 # define CALC_MS_CLOCK(x) static_cast<int>((x) / (CLOCKS_PER_SEC / 1000))
31 # define CALC_NS_AVG_CLOCK(x, y) (1000000LL * static_cast<long long>((x) / (CLOCKS_PER_SEC / 1000)) / (y ? y : 1))
34 struct benchmark_no_trivial_message_t {
35 ~benchmark_no_trivial_message_t() {}
38 benchmark_no_trivial_message_t() :
data(0) {}
39 template <
class TFirst,
class... TRest,
typename = std::enable_if_t<!std::is_same_v<std::decay_t<TFirst>, int64_t>>>
40 benchmark_no_trivial_message_t(TFirst &&, TRest &&...) :
data(0) {}
43 benchmark_no_trivial_message_t(int64_t input) :
data(input) {}
44 benchmark_no_trivial_message_t(
const benchmark_no_trivial_message_t &) =
default;
45 benchmark_no_trivial_message_t(benchmark_no_trivial_message_t &&) =
default;
46 benchmark_no_trivial_message_t &operator=(
const benchmark_no_trivial_message_t &) =
default;
47 benchmark_no_trivial_message_t &operator=(benchmark_no_trivial_message_t &&) =
default;
52 LIBCOPP_COPP_NAMESPACE_BEGIN
54 struct std_coroutine_default_error_transform<benchmark_no_trivial_message_t> {
55 using type = benchmark_no_trivial_message_t;
56 type operator()(promise_status in)
const {
return benchmark_no_trivial_message_t{
static_cast<int64_t
>(in)}; }
58 LIBCOPP_COPP_NAMESPACE_END
60 using benchmark_task_future_type = cotask::task_future<benchmark_no_trivial_message_t, void>;
61 using benchmark_generator_future_type = copp::generator_future<benchmark_no_trivial_message_t>;
63 std::vector<benchmark_task_future_type> g_benchmark_task_list;
64 std::vector<benchmark_generator_future_type::context_pointer_type> g_benchmark_generator_list;
66 benchmark_task_future_type run_benchmark(
size_t idx,
int left_switch_count) {
69 benchmark_generator_future_type generator{[idx](benchmark_generator_future_type::context_pointer_type ctx) {
70 g_benchmark_generator_list[idx] = std::move(ctx);
72 while (left_switch_count-- >= 0) {
73 generator.get_context()->reset_value();
74 auto offset = co_await generator;
75 result += offset.data;
78 co_return benchmark_no_trivial_message_t{result};
82 int max_task_number = 100000;
85 g_benchmark_task_list.reserve(
static_cast<size_t>(max_task_number));
86 g_benchmark_generator_list.resize(
static_cast<size_t>(max_task_number),
nullptr);
88 printf(
"### Round: %d ###\n", index);
90 time_t begin_time = time(
nullptr);
94 while (g_benchmark_task_list.size() <
static_cast<size_t>(max_task_number)) {
95 g_benchmark_task_list.push_back(run_benchmark(g_benchmark_task_list.size(),
switch_count));
97 for (
auto &task_inst : g_benchmark_task_list) {
101 time_t end_time = time(
nullptr);
103 printf(
"create %d task(s) and generator(s), cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number,
104 static_cast<int>(end_time - begin_time),
CALC_MS_CLOCK(end_clock - begin_clock),
107 begin_time = end_time;
108 begin_clock = end_clock;
111 bool continue_flag =
true;
112 long long real_switch_times =
static_cast<long long>(0);
115 while (continue_flag) {
117 continue_flag =
false;
118 for (
auto &generator_context : g_benchmark_generator_list) {
119 benchmark_generator_future_type::context_pointer_type move_context;
120 move_context.swap(generator_context);
122 move_context->set_value(benchmark_no_trivial_message_t{round});
124 continue_flag =
true;
129 end_time = time(
nullptr);
131 printf(
"resume %d task(s) and generator(s) for %lld times, cost time: %d s, clock time: %d ms, avg: %lld ns\n",
132 max_task_number, real_switch_times,
static_cast<int>(end_time - begin_time),
135 begin_time = end_time;
136 begin_clock = end_clock;
138 g_benchmark_task_list.clear();
139 g_benchmark_generator_list.clear();
141 end_time = time(
nullptr);
143 printf(
"remove %d task(s), cost time: %d s, clock time: %d ms, avg: %lld ns\n", max_task_number,
144 static_cast<int>(end_time - begin_time),
CALC_MS_CLOCK(end_clock - begin_clock),
148 int main(
int argc,
char *argv[]) {
149 puts(
"###################### std task - reuse generator - no trivial ###################");
150 printf(
"########## Cmd:");
151 for (
int i = 0; i < argc; ++i) {
152 printf(
" %s", argv[i]);
157 max_task_number = atoi(argv[1]);
164 for (
int i = 1; i <= 5; ++i) {
171 puts(
"task_future disabled.");
177 puts(
"std coroutine is not supported by current compiler.");
constexpr auto data(TCONTAINER &&container) -> decltype(container.data())
#define CALC_NS_AVG_CLOCK(x, y)
static void benchmark_round(int index)