From 36caebcf45bfcd0056d013b319b2adb18b68d2cd Mon Sep 17 00:00:00 2001 From: owent Date: Tue, 15 Sep 2026 14:27:08 +0800 Subject: [PATCH 1/5] Keep FIFO for channel wait and resume --- CHANGELOG.md | 9 +++ include/libcopp/coroutine/stackful_channel.h | 47 +++++++++++++-- .../libcopp/coroutine/std_coroutine_common.h | 47 +++++++++++++-- src/libcopp/coroutine/stackful_channel.cpp | 48 +++++++++------- .../coroutine/std_coroutine_common.cpp | 48 +++++++++------- test/case/coroutine_context_channel_test.cpp | 53 +++++++++++++++++ test/case/task_promise_test.cpp | 57 +++++++++++++++++++ 7 files changed, 259 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ece462c..5f012a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # CHANGELOG +## Unreleased + +1. Resume multiple callers of `promise_caller_manager` (C++20 coroutine) and `stackful_channel_context_base` + (stackful channel) in registration (FIFO) order instead of hash order. The multi-caller containers are now a + dual index of an order-preserving list and a hash map, so waiters queued behind the same task or channel wake + in the order they registered, matching the legacy stackful `next_list` behavior, while dedup-on-add and + passive removal stay O(1). Duplicate registrations of the same handle are now also ignored when + `LIBCOPP_MACRO_ENABLE_STD_VARIANT` is off. + ## 2.3.2 1. Rewrite document. diff --git a/include/libcopp/coroutine/stackful_channel.h b/include/libcopp/coroutine/stackful_channel.h index c7aa807..de7c105 100644 --- a/include/libcopp/coroutine/stackful_channel.h +++ b/include/libcopp/coroutine/stackful_channel.h @@ -12,8 +12,9 @@ // clang-format on #include +#include #include -#include +#include #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR # include @@ -222,13 +223,49 @@ class stackful_channel_context_base { LIBCOPP_COPP_API void wake(); private: - using multi_caller_set = std::unordered_set; + // Keep multiple callers in registration order so resume_callers() wakes them in FIFO order, which + // matches the C++20 coroutine backend's promise_caller_manager and is the least surprising + // semantics. The list keeps the wake order and allows O(1) removal by iterator, while the hash + // index keeps dedup-on-add and passive removal O(1) as well. + struct multi_caller_container { + using list_type = std::list; + using index_type = std::unordered_map; + + list_type callers; + index_type index; + + inline bool add(const handle_delegate &delegate) { + if (index.find(delegate) != index.end()) { + return false; + } + auto back_iter = callers.insert(callers.end(), delegate); + index.emplace(delegate, back_iter); + return true; + } + + inline bool remove(const handle_delegate &delegate) { + auto iter = index.find(delegate); + if (iter == index.end()) { + return false; + } + callers.erase(iter->second); + index.erase(iter); + return true; + } + + inline void swap(multi_caller_container &other) noexcept { + callers.swap(other.callers); + index.swap(other.index); + } + + inline size_t size() const noexcept { return index.size(); } + }; #if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT - std::variant callers_; + std::variant callers_; #else handle_delegate unique_caller_; - // Mostly, there is only one caller for a promise, we needn't hash map to store one handle - std::unique_ptr multiple_callers_; + // Mostly, there is only one caller for a promise, we needn't container to store one handle + std::unique_ptr multiple_callers_; #endif }; diff --git a/include/libcopp/coroutine/std_coroutine_common.h b/include/libcopp/coroutine/std_coroutine_common.h index d7f10b0..a354a23 100644 --- a/include/libcopp/coroutine/std_coroutine_common.h +++ b/include/libcopp/coroutine/std_coroutine_common.h @@ -12,9 +12,10 @@ #include #include +#include #include #include -#include +#include #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR # include @@ -189,13 +190,49 @@ class promise_caller_manager { } }; - using multi_caller_set = std::unordered_set; + // Keep multiple callers in registration order so resume_callers() wakes them in FIFO order, which + // matches the stackful backend's next_list behavior and is the least surprising semantics. The + // list keeps the wake order and allows O(1) removal by iterator, while the hash index keeps + // dedup-on-add and passive removal O(1) as well. + struct multi_caller_container { + using list_type = std::list; + using index_type = std::unordered_map; + + list_type callers; + index_type index; + + inline bool add(const handle_delegate &delegate) { + if (index.find(delegate) != index.end()) { + return false; + } + auto back_iter = callers.insert(callers.end(), delegate); + index.emplace(delegate, back_iter); + return true; + } + + inline bool remove(const handle_delegate &delegate) { + auto iter = index.find(delegate); + if (iter == index.end()) { + return false; + } + callers.erase(iter->second); + index.erase(iter); + return true; + } + + inline void swap(multi_caller_container &other) noexcept { + callers.swap(other.callers); + index.swap(other.index); + } + + inline size_t size() const noexcept { return index.size(); } + }; # if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT - std::variant callers_; + std::variant callers_; # else handle_delegate unique_caller_; - // Mostly, there is only one caller for a promise, we needn't hash map to store one handle - std::unique_ptr multiple_callers_; + // Mostly, there is only one caller for a promise, we needn't container to store one handle + std::unique_ptr multiple_callers_; # endif }; diff --git a/src/libcopp/coroutine/stackful_channel.cpp b/src/libcopp/coroutine/stackful_channel.cpp index 914f198..acc595b 100644 --- a/src/libcopp/coroutine/stackful_channel.cpp +++ b/src/libcopp/coroutine/stackful_channel.cpp @@ -44,8 +44,8 @@ LIBCOPP_COPP_API void stackful_channel_context_base::add_caller(handle_delegate } #if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT - if (std::holds_alternative(callers_)) { - std::get(callers_).insert(handle); + if (std::holds_alternative(callers_)) { + std::get(callers_).add(handle); return; } @@ -54,21 +54,29 @@ LIBCOPP_COPP_API void stackful_channel_context_base::add_caller(handle_delegate return; } - // convert to multiple caller - multi_caller_set callers; - callers.insert(std::get(callers_)); - callers.insert(handle); - callers_.emplace(std::move(callers)); + if (std::get(callers_) == handle) { + return; + } + + // convert to multiple callers and keep the registration order + multi_caller_container callers; + callers.add(std::get(callers_)); + callers.add(handle); + callers_.emplace(std::move(callers)); #else if (!unique_caller_) { unique_caller_ = handle; return; } + if (unique_caller_ == handle) { + return; + } + if (!multiple_callers_) { - multiple_callers_.reset(new multi_caller_set()); + multiple_callers_.reset(new multi_caller_container()); } - multiple_callers_->insert(handle); + multiple_callers_->add(handle); #endif } @@ -76,8 +84,8 @@ LIBCOPP_COPP_API bool stackful_channel_context_base::remove_caller(handle_delega bool has_caller = false; do { #if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT - if (std::holds_alternative(callers_)) { - has_caller = std::get(callers_).erase(handle) > 0; + if (std::holds_alternative(callers_)) { + has_caller = std::get(callers_).remove(handle); break; } @@ -93,7 +101,7 @@ LIBCOPP_COPP_API bool stackful_channel_context_base::remove_caller(handle_delega } if (multiple_callers_) { - has_caller = multiple_callers_->erase(handle) > 0; + has_caller = multiple_callers_->remove(handle); } #endif } while (false); @@ -111,10 +119,10 @@ LIBCOPP_COPP_API size_t stackful_channel_context_base::resume_callers() { caller.resume_handle(caller.handle_data, this); ++resume_count; } - } else if (std::holds_alternative(callers_)) { - multi_caller_set callers; - callers.swap(std::get(callers_)); - for (auto &caller : callers) { + } else if (std::holds_alternative(callers_)) { + multi_caller_container callers; + callers.swap(std::get(callers_)); + for (auto &caller : callers.callers) { if (caller.handle_data && caller.resume_handle) { caller.resume_handle(caller.handle_data, this); ++resume_count; @@ -124,7 +132,7 @@ LIBCOPP_COPP_API size_t stackful_channel_context_base::resume_callers() { #else auto unique_caller = unique_caller_; unique_caller_ = nullptr; - std::unique_ptr multiple_callers; + std::unique_ptr multiple_callers; multiple_callers.swap(multiple_callers_); // The promise object may be destroyed after first caller.resume() @@ -134,7 +142,7 @@ LIBCOPP_COPP_API size_t stackful_channel_context_base::resume_callers() { } if (multiple_callers) { - for (auto &caller : *multiple_callers) { + for (auto &caller : multiple_callers->callers) { if (caller.handle_data && caller.resume_handle) { caller.resume_handle(caller.handle_data, this); ++resume_count; @@ -149,8 +157,8 @@ LIBCOPP_COPP_API bool stackful_channel_context_base::has_multiple_callers() cons #if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT if (std::holds_alternative(callers_)) { return false; - } else if (std::holds_alternative(callers_)) { - return std::get(callers_).size() > 1; + } else if (std::holds_alternative(callers_)) { + return std::get(callers_).size() > 1; } return false; #else diff --git a/src/libcopp/coroutine/std_coroutine_common.cpp b/src/libcopp/coroutine/std_coroutine_common.cpp index bf41cad..8a9a0b3 100644 --- a/src/libcopp/coroutine/std_coroutine_common.cpp +++ b/src/libcopp/coroutine/std_coroutine_common.cpp @@ -35,8 +35,8 @@ LIBCOPP_COPP_API void promise_caller_manager::add_caller(handle_delegate delegat } # if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT - if (std::holds_alternative(callers_)) { - std::get(callers_).insert(delegate); + if (std::holds_alternative(callers_)) { + std::get(callers_).add(delegate); return; } @@ -45,21 +45,29 @@ LIBCOPP_COPP_API void promise_caller_manager::add_caller(handle_delegate delegat return; } - // convert to multiple caller - multi_caller_set callers; - callers.insert(std::get(callers_)); - callers.insert(delegate); - callers_.emplace(std::move(callers)); + if (std::get(callers_) == delegate) { + return; + } + + // convert to multiple callers and keep the registration order + multi_caller_container callers; + callers.add(std::get(callers_)); + callers.add(delegate); + callers_.emplace(std::move(callers)); # else if (!unique_caller_.handle) { unique_caller_ = delegate; return; } + if (unique_caller_ == delegate) { + return; + } + if (!multiple_callers_) { - multiple_callers_.reset(new multi_caller_set()); + multiple_callers_.reset(new multi_caller_container()); } - multiple_callers_->insert(delegate); + multiple_callers_->add(delegate); # endif } @@ -67,8 +75,8 @@ LIBCOPP_COPP_API bool promise_caller_manager::remove_caller(handle_delegate dele bool has_caller = false; do { # if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT - if (std::holds_alternative(callers_)) { - has_caller = std::get(callers_).erase(delegate) > 0; + if (std::holds_alternative(callers_)) { + has_caller = std::get(callers_).remove(delegate); break; } @@ -84,7 +92,7 @@ LIBCOPP_COPP_API bool promise_caller_manager::remove_caller(handle_delegate dele } if (multiple_callers_) { - has_caller = multiple_callers_->erase(delegate) > 0; + has_caller = multiple_callers_->remove(delegate); } # endif } while (false); @@ -103,10 +111,10 @@ LIBCOPP_COPP_API size_t promise_caller_manager::resume_callers() { caller.handle.resume(); ++resume_count; } - } else if (std::holds_alternative(callers_)) { - multi_caller_set callers; - callers.swap(std::get(callers_)); - for (auto &caller : callers) { + } else if (std::holds_alternative(callers_)) { + multi_caller_container callers; + callers.swap(std::get(callers_)); + for (auto &caller : callers.callers) { if (caller.handle && !caller.handle.done() && (nullptr == caller.promise || !caller.promise->check_flag(promise_flag::kDestroying))) { type_erased_handle_type handle = caller.handle; @@ -118,7 +126,7 @@ LIBCOPP_COPP_API size_t promise_caller_manager::resume_callers() { # else auto unique_caller = unique_caller_; unique_caller_ = nullptr; - std::unique_ptr multiple_callers; + std::unique_ptr multiple_callers; multiple_callers.swap(multiple_callers_); // The promise object may be destroyed after first caller.resume() @@ -129,7 +137,7 @@ LIBCOPP_COPP_API size_t promise_caller_manager::resume_callers() { } if (multiple_callers) { - for (auto &caller : *multiple_callers) { + for (auto &caller : multiple_callers->callers) { if (caller.handle && !caller.handle.done() && (nullptr == caller.promise || !caller.promise->check_flag(promise_flag::kDestroying))) { type_erased_handle_type handle = caller.handle; @@ -146,8 +154,8 @@ LIBCOPP_COPP_API bool promise_caller_manager::has_multiple_callers() const noexc # if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT if (std::holds_alternative(callers_)) { return false; - } else if (std::holds_alternative(callers_)) { - return std::get(callers_).size() > 1; + } else if (std::holds_alternative(callers_)) { + return std::get(callers_).size() > 1; } return false; # else diff --git a/test/case/coroutine_context_channel_test.cpp b/test/case/coroutine_context_channel_test.cpp index 26184cd..5cfc97b 100644 --- a/test/case/coroutine_context_channel_test.cpp +++ b/test/case/coroutine_context_channel_test.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "frame/test_macros.h" @@ -490,3 +491,55 @@ CASE_TEST(coroutine_channel, fiber_channel_pointer) { delete[] stack_buff; } #endif + +namespace { +struct test_context_channel_fifo_context : public copp::stackful_channel_context_base {}; + +std::vector g_test_coroutine_channel_fifo_order; + +int test_context_channel_fifo_resume(void *handle_data, copp::stackful_channel_context_base *) { + g_test_coroutine_channel_fifo_order.push_back(*reinterpret_cast(handle_data)); + return 0; +} +} // namespace + +CASE_TEST(coroutine_channel, multiple_callers_resume_fifo) { + constexpr int k_caller_count = 8; + int caller_indexes[k_caller_count]; + copp::stackful_channel_handle_delegate callers[k_caller_count]; + test_context_channel_fifo_context context; + + g_test_coroutine_channel_fifo_order.clear(); + for (int index = 0; index < k_caller_count; ++index) { + caller_indexes[index] = index; + callers[index].handle_data = &caller_indexes[index]; + callers[index].resume_handle = &test_context_channel_fifo_resume; + context.add_caller(callers[index]); + } + // A repeated registration of the same handle is ignored. + context.add_caller(callers[3]); + + CASE_EXPECT_TRUE(context.has_multiple_callers()); + CASE_EXPECT_EQ(k_caller_count, static_cast(context.resume_callers())); + CASE_EXPECT_EQ(k_caller_count, static_cast(g_test_coroutine_channel_fifo_order.size())); + for (int index = 0; index < k_caller_count; ++index) { + CASE_EXPECT_EQ(index, g_test_coroutine_channel_fifo_order[static_cast(index)]); + } + + // A handle removed and registered again joins the back of the queue. + g_test_coroutine_channel_fifo_order.clear(); + for (int index = 0; index < k_caller_count; ++index) { + context.add_caller(callers[index]); + } + CASE_EXPECT_TRUE(context.remove_caller(callers[2])); + context.add_caller(callers[2]); + + const int expected_order[k_caller_count] = {0, 1, 3, 4, 5, 6, 7, 2}; + CASE_EXPECT_EQ(k_caller_count, static_cast(context.resume_callers())); + CASE_EXPECT_EQ(k_caller_count, static_cast(g_test_coroutine_channel_fifo_order.size())); + if (k_caller_count == static_cast(g_test_coroutine_channel_fifo_order.size())) { + for (int index = 0; index < k_caller_count; ++index) { + CASE_EXPECT_EQ(expected_order[index], g_test_coroutine_channel_fifo_order[static_cast(index)]); + } + } +} diff --git a/test/case/task_promise_test.cpp b/test/case/task_promise_test.cpp index b2016ec..7466500 100644 --- a/test/case/task_promise_test.cpp +++ b/test/case/task_promise_test.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "frame/test_macros.h" @@ -403,6 +404,62 @@ CASE_TEST(task_promise, task_future_await_task) { CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count); } +namespace { +std::list g_task_future_fifo_blocker_contexts; +std::vector g_task_future_fifo_resume_order; + +static void generator_fifo_blocker_suspend_callback(generator_future_int_type::context_pointer_type ctx) { + g_task_future_fifo_blocker_contexts.push_back(ctx); +} +static void generator_fifo_blocker_resume_callback(const generator_future_int_type::context_type &) {} + +static task_future_int_type task_func_fifo_blocker() { + generator_future_int_type generator{generator_fifo_blocker_suspend_callback, + generator_fifo_blocker_resume_callback}; + auto res = co_await generator; + co_return res; +} + +static callable_future_int_type task_future_func_fifo_waiter(task_future_int_type waiting, int index) { + int res = co_await waiting; + if (res >= 0) { + g_task_future_fifo_resume_order.push_back(index); + } + co_return res; +} +} // namespace + +CASE_TEST(task_promise, task_future_multiple_callers_resume_fifo) { + g_task_future_fifo_blocker_contexts.clear(); + g_task_future_fifo_resume_order.clear(); + + task_future_int_type blocker = task_func_fifo_blocker(); + CASE_EXPECT_TRUE(blocker.start()); + CASE_EXPECT_FALSE(blocker.is_exiting()); + CASE_EXPECT_EQ(1, static_cast(g_task_future_fifo_blocker_contexts.size())); + + constexpr int k_waiter_count = 8; + std::vector waiters; + for (int index = 0; index < k_waiter_count; ++index) { + waiters.push_back(task_future_func_fifo_waiter(blocker, index)); + // Each waiter registers into the blocker's caller manager and stays parked. + CASE_EXPECT_FALSE(waiters.back().is_ready()); + CASE_EXPECT_FALSE(blocker.is_exiting()); + } + + // Completing the blocker resumes every caller in registration (FIFO) order. + auto pending_context = g_task_future_fifo_blocker_contexts.front(); + g_task_future_fifo_blocker_contexts.pop_front(); + pending_context->set_value(0); + + CASE_EXPECT_TRUE(blocker.is_exiting()); + CASE_EXPECT_EQ(k_waiter_count, static_cast(g_task_future_fifo_resume_order.size())); + for (int index = 0; index < k_waiter_count; ++index) { + CASE_EXPECT_EQ(index, g_task_future_fifo_resume_order[static_cast(index)]); + CASE_EXPECT_TRUE(waiters[static_cast(index)].is_ready()); + } +} + namespace { static callable_future_int_type task_func_await_callable_and_be_killed() { auto u = task_future_func_int_l2(13); From ea13274e45cc4c53c37546097a37fa02c533a841 Mon Sep 17 00:00:00 2001 From: owent Date: Tue, 15 Sep 2026 15:33:01 +0800 Subject: [PATCH 2/5] Update deps --- .github/workflows/main.yml | 24 ++++++++++++------------ .github/workflows/stale.yml | 2 +- .github/workflows/sync.yml | 2 +- docs/requirements.txt | 12 ++++++------ 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3313504..3e1ac8d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: CI Job shell: bash run: | @@ -30,7 +30,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: lfs: "true" - name: Build & Test @@ -103,7 +103,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Build & Test shell: bash env: @@ -141,7 +141,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Build & Test shell: pwsh env: @@ -165,7 +165,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Build & Test shell: bash env: @@ -173,12 +173,12 @@ jobs: run: | C:/msys64/msys2_shell.cmd -mingw64 -defterm -no-start -here -lc "ci/do_ci.sh msys2.mingw.test" - name: Cache packages - uses: actions/cache@v5 + uses: actions/cache@v6 with: path: | C:/msys64/var/cache/pacman/pkg C:/msys64/var/lib/pacman - key: ${{ runner.os }}-${ hashFiles('.github/workflows/main.yml') } }} + key: ${{ runner.os }}-${{ hashFiles('.github/workflows/main.yml') }} coverage: # job id, can be any string name: Coverage # This job runs on Linux @@ -192,7 +192,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Generate coverage shell: bash env: @@ -209,7 +209,7 @@ jobs: fi bash ci/do_ci.sh coverage ; - name: Uploaded code coverage - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v7 with: token: ${{secrets.CODECOV_TOKEN}} # not required for public repos fail_ci_if_error: true @@ -230,7 +230,7 @@ jobs: security-events: write steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Build shell: bash env: @@ -240,7 +240,7 @@ jobs: run: | bash ci/do_ci.sh codeql.configure - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: config-file: ./.github/codeql/codeql-config.yml - name: Build @@ -252,6 +252,6 @@ jobs: run: | bash ci/do_ci.sh codeql.build - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 with: category: "/language:cpp" diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 8ea5ab0..1a1b0e3 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,7 +7,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v9 + - uses: actions/stale@v11 with: stale-issue-message: "This issue was marked as stale due to lack of activity." days-before-issue-stale: 90 diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml index 3881ebe..d3ccd15 100644 --- a/.github/workflows/sync.yml +++ b/.github/workflows/sync.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: fetch-depth: 200 lfs: "true" diff --git a/docs/requirements.txt b/docs/requirements.txt index 04f7b56..1241b8e 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,7 +1,7 @@ setuptools>=41.2.0 -mkdocs>=1.5.0 -mkdocs-material>=9.5.0 -mkdocs-include-markdown-plugin>=7.2.0 -mkdocs-macros-plugin>=1.0.0 -mkdocs-drawio>=1.13.0 -pymdown-extensions>=10.0 +mkdocs>=1.6.1 +mkdocs-material>=9.7.7 +mkdocs-include-markdown-plugin>=7.3.0 +mkdocs-macros-plugin>=1.5.0 +mkdocs-drawio>=1.16.3 +pymdown-extensions>=12.0 From 7307ec1f1c89c887cf2ad81edf61972b2873992a Mon Sep 17 00:00:00 2001 From: owent Date: Tue, 15 Sep 2026 15:34:14 +0800 Subject: [PATCH 3/5] Update changlog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f012a7..26ddca2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # CHANGELOG -## Unreleased +## 2.3.3 1. Resume multiple callers of `promise_caller_manager` (C++20 coroutine) and `stackful_channel_context_base` (stackful channel) in registration (FIFO) order instead of hash order. The multi-caller containers are now a @@ -8,6 +8,8 @@ in the order they registered, matching the legacy stackful `next_list` behavior, while dedup-on-add and passive removal stay O(1). Duplicate registrations of the same handle are now also ignored when `LIBCOPP_MACRO_ENABLE_STD_VARIANT` is off. +2. Update dependencies. +3. Update benchmark results. ## 2.3.2 From e14bf400c9facbed0f12e8041fc53284688a3592 Mon Sep 17 00:00:00 2001 From: owent Date: Tue, 15 Sep 2026 18:20:17 +0800 Subject: [PATCH 4/5] Update reports --- atframework/cmake-toolset | 2 +- docs/benchmarks/index.md | 4 +- docs/benchmarks/linux.md | 9 +- docs/benchmarks/windows.md | 11 +- docs/reports/linux_benchmark_report.txt | 1174 +++++++++++++++++- docs/reports/windows_benchmark_report.txt | 391 ++++-- docs/requirements-vscode.txt | 12 +- test/case/coroutine_context_channel_test.cpp | 39 + test/case/task_promise_test.cpp | 57 +- 9 files changed, 1540 insertions(+), 159 deletions(-) diff --git a/atframework/cmake-toolset b/atframework/cmake-toolset index 3412078..0f36e09 160000 --- a/atframework/cmake-toolset +++ b/atframework/cmake-toolset @@ -1 +1 @@ -Subproject commit 34120785c105ddaacf84b76c365063391c656db2 +Subproject commit 0f36e09ff78ae16173c4e3844c14fa1194429934 diff --git a/docs/benchmarks/index.md b/docs/benchmarks/index.md index 6cb2b45..b53374e 100644 --- a/docs/benchmarks/index.md +++ b/docs/benchmarks/index.md @@ -1,6 +1,6 @@ # Benchmarks -This section summarizes the stress test reports captured in `docs/reports` and provides the raw logs for reference. +This section summarizes the benchmark reports captured in `docs/reports` and provides the raw logs for reference. ## How to run @@ -18,5 +18,5 @@ This section summarizes the stress test reports captured in `docs/reports` and p ## Summary -- Each report measures allocate/create/switch/remove cycles for coroutine contexts and tasks with different stack allocators. +- Each report measures allocate/create/switch/remove cycles for stackful coroutine contexts and cotask tasks (with different stack allocators), as well as C++20 std coroutine callable/task generator benchmarks. - Use the raw logs below for precise numbers and environment details. diff --git a/docs/benchmarks/linux.md b/docs/benchmarks/linux.md index 442c9c7..5010f5e 100644 --- a/docs/benchmarks/linux.md +++ b/docs/benchmarks/linux.md @@ -2,11 +2,12 @@ ## Summary -- Environment: Linux 3.14.3-200.fc20.x86_64 (gcc 4.8.2) -- CPU: AMD Phenom(tm) II X4 830 Processor (800MHz- 2800MHz) -- Memory: 8GB DDR3-1333 +- Environment: GitHub Actions `ubuntu-latest` (Ubuntu 24.04), gcc 13.3.0 +- CPU: GitHub-hosted runner (4 vCPU) +- Memory: 16 GB - Build type: RelWithDebInfo -- Thread number: 1, stack memory cost 2.0GB +- Thread number: 1 +- Source: [CI run 34942431606](https://github.com/owent/libcopp/actions/runs/34942431606) — job "Unix Build (gcc, ON)" ## Raw report diff --git a/docs/benchmarks/windows.md b/docs/benchmarks/windows.md index cf64798..83b44e6 100644 --- a/docs/benchmarks/windows.md +++ b/docs/benchmarks/windows.md @@ -2,11 +2,12 @@ ## Summary -- Environment: Windows 7, Visual Studio 2013 (VC 18) -- CPU: AMD Phenom(tm) II X4 830 Processor (800MHz- 2800MHz) -- Memory: 8GB DDR3-1333 -- Build type: Release -- Thread number: 1, stack memory cost 2.0GB +- Environment: GitHub Actions `windows-latest`, MinGW-w64 gcc 16.2.0 +- CPU: GitHub-hosted runner (4 vCPU) +- Memory: 16 GB +- Build type: RelWithDebInfo +- Thread number: 1 +- Source: [CI run 34942431606](https://github.com/owent/libcopp/actions/runs/34942431606) — job "MinGW Build (ON)". The MSVC (Visual Studio 17 2022) job logs were truncated by GitHub, so MinGW-w64 results are shown. ## Raw report diff --git a/docs/reports/linux_benchmark_report.txt b/docs/reports/linux_benchmark_report.txt index 6f17753..1684052 100755 --- a/docs/reports/linux_benchmark_report.txt +++ b/docs/reports/linux_benchmark_report.txt @@ -1,75 +1,1117 @@ ======================================================================================= -Env: Linux version 3.14.3-200.fc20.x86_64 (mockbuild@bkernel02) (gcc version 4.8.2 20131212 (Red Hat 4.8.2-7) (GCC) ) #1 SMP Tue May 6 19:00:18 UTC 2014 +Source: GitHub Actions - job "Unix Build (ubuntu-latest, x64-linux, gcc, ON)" + https://github.com/owent/libcopp/actions/runs/34942431606 +Env: Ubuntu 24.04 (GitHub-hosted ubuntu-latest runner), gcc 13.3.0 System: Linux -CPU: AMD Phenom(tm) II X4 830 Processor (800MHz- 2800MHz) -Memory: 8GB DDR3-1333 +CPU: GitHub-hosted runner (4 vCPU) +Memory: 16 GB CMake Build Type: RelWithDebInfo -Run Env => thread number: 1, stack memory cost 2.0GB -Compile Options:-O2 -g -DNDEBUG -ggdb -std=gnu++11 -Wall -Werror -rdynamic -Wno-unused-local-typedefs -fsplit-stack +Run Env => thread number: 1 +Each "Cmd" line shows the benchmark binary and its arguments: +Captured from CI: 2026-09-15 +======================================================================================= +###################### context coroutine (stack using default allocator[mmap]) ################### +########## Cmd: sample/libcopp_sample_benchmark_coroutine 30000 100 64 +allocate 30000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 3 ns +create 30000 coroutine, cost time: 0 s, clock time: 230 ms, avg: 7697 ns +switch 30000 coroutine contest 3000000 times, cost time: 0 s, clock time: 227 ms, avg: 75 ns +remove 30000 coroutine, cost time: 0 s, clock time: 205 ms, avg: 6833 ns +###################### context coroutine (stack using default allocator[mmap]) ################### +########## Cmd: sample/libcopp_sample_benchmark_coroutine 1000 1000 2048 +allocate 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 3 ns +create 1000 coroutine, cost time: 0 s, clock time: 7 ms, avg: 7957 ns +switch 1000 coroutine contest 1000000 times, cost time: 0 s, clock time: 67 ms, avg: 67 ns +remove 1000 coroutine, cost time: 0 s, clock time: 6 ms, avg: 6569 ns +###################### context coroutine (stack using default allocator[mmap]) ################### +########## Cmd: sample/libcopp_sample_benchmark_coroutine 1 1000000 16 +allocate 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 902 ns +create 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 18625 ns +switch 1 coroutine contest 1000000 times, cost time: 0 s, clock time: 51 ms, avg: 51 ns +remove 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 25227 ns +###################### context coroutine (stack using malloc/free) ################### +########## Cmd: sample/libcopp_sample_benchmark_coroutine_malloc 30000 100 64 +allocate 30000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 3 ns +create 30000 coroutine, cost time: 0 s, clock time: 68 ms, avg: 2272 ns +switch 30000 coroutine contest 3000000 times, cost time: 1 s, clock time: 246 ms, avg: 82 ns +remove 30000 coroutine, cost time: 0 s, clock time: 129 ms, avg: 4303 ns +###################### context coroutine (stack using malloc/free) ################### +########## Cmd: sample/libcopp_sample_benchmark_coroutine_malloc 1000 1000 2048 +allocate 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 4 ns +create 1000 coroutine, cost time: 0 s, clock time: 8 ms, avg: 8121 ns +switch 1000 coroutine contest 1000000 times, cost time: 0 s, clock time: 62 ms, avg: 62 ns +remove 1000 coroutine, cost time: 0 s, clock time: 6 ms, avg: 6311 ns +###################### context coroutine (stack using malloc/free) ################### +########## Cmd: sample/libcopp_sample_benchmark_coroutine_malloc 1 1000000 16 +allocate 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 942 ns +create 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 10700 ns +switch 1 coroutine contest 1000000 times, cost time: 0 s, clock time: 52 ms, avg: 52 ns +remove 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 11341 ns +###################### context coroutine (stack using memory pool) ################### +########## Cmd: sample/libcopp_sample_benchmark_coroutine_mem_pool 30000 100 64 +allocate 30000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 3 ns +create 30000 coroutine, cost time: 0 s, clock time: 2 ms, avg: 94 ns +switch 30000 coroutine contest 3000000 times, cost time: 0 s, clock time: 296 ms, avg: 98 ns +remove 30000 coroutine, cost time: 0 s, clock time: 7 ms, avg: 263 ns ###################### context coroutine (stack using memory pool) ################### -########## Cmd: sample/sample_stress_test_coroutine_mem_pool 10000 1000 200 -allocate 10000 coroutine, cost time: 0 s, clock time: 4 ms, avg: 400 ns -create 10000 coroutine, cost time: 0 s, clock time: 50 ms, avg: 5000 ns -switch 10000 coroutine contest 10000000 times, cost time: 4 s, clock time: 3706 ms, avg: 370 ns -remove 10000 coroutine, cost time: 0 s, clock time: 9 ms, avg: 900 ns -########## Cmd: sample/sample_stress_test_coroutines_mem_pool 1000 1000 2048 +########## Cmd: sample/libcopp_sample_benchmark_coroutine_mem_pool 1000 1000 2048 +allocate 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 7 ns +create 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 92 ns +switch 1000 coroutine contest 1000000 times, cost time: 0 s, clock time: 55 ms, avg: 55 ns +remove 1000 coroutine, cost time: 0 s, clock time: 7 ms, avg: 7445 ns +###################### context coroutine (stack using memory pool) ################### +########## Cmd: sample/libcopp_sample_benchmark_coroutine_mem_pool 1 1000000 16 +allocate 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 290 ns +create 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 6823 ns +switch 1 coroutine contest 1000000 times, cost time: 0 s, clock time: 51 ms, avg: 51 ns +remove 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 8886 ns +###################### context coroutine (stack using stack pool) ################### +########## Cmd: sample/libcopp_sample_benchmark_coroutine_stack_pool 30000 100 64 +### Round: 1 ### +allocate 30000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 3 ns +create 30000 coroutine, cost time: 0 s, clock time: 235 ms, avg: 7842 ns +switch 30000 coroutine contest 3000000 times, cost time: 0 s, clock time: 350 ms, avg: 116 ns +remove 30000 coroutine, cost time: 0 s, clock time: 2 ms, avg: 67 ns +### Round: 2 ### +allocate 30000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 3 ns +create 30000 coroutine, cost time: 0 s, clock time: 1 ms, avg: 65 ns +switch 30000 coroutine contest 3000000 times, cost time: 1 s, clock time: 371 ms, avg: 123 ns +remove 30000 coroutine, cost time: 0 s, clock time: 1 ms, avg: 35 ns +### Round: 3 ### +allocate 30000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 0 ns +create 30000 coroutine, cost time: 0 s, clock time: 1 ms, avg: 61 ns +switch 30000 coroutine contest 3000000 times, cost time: 0 s, clock time: 287 ms, avg: 95 ns +remove 30000 coroutine, cost time: 0 s, clock time: 1 ms, avg: 36 ns +### Round: 4 ### +allocate 30000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 0 ns +create 30000 coroutine, cost time: 0 s, clock time: 1 ms, avg: 61 ns +switch 30000 coroutine contest 3000000 times, cost time: 0 s, clock time: 263 ms, avg: 87 ns +remove 30000 coroutine, cost time: 0 s, clock time: 1 ms, avg: 35 ns +### Round: 5 ### +allocate 30000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 0 ns +create 30000 coroutine, cost time: 0 s, clock time: 1 ms, avg: 61 ns +switch 30000 coroutine contest 3000000 times, cost time: 1 s, clock time: 318 ms, avg: 106 ns +remove 30000 coroutine, cost time: 0 s, clock time: 1 ms, avg: 39 ns +###################### context coroutine (stack using stack pool) ################### +########## Cmd: sample/libcopp_sample_benchmark_coroutine_stack_pool 1000 1000 2048 +### Round: 1 ### +allocate 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 3 ns +create 1000 coroutine, cost time: 0 s, clock time: 7 ms, avg: 7936 ns +switch 1000 coroutine contest 1000000 times, cost time: 0 s, clock time: 65 ms, avg: 65 ns +remove 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 91 ns +### Round: 2 ### allocate 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 0 ns -create 1000 coroutine, cost time: 0 s, clock time: 5 ms, avg: 5000 ns -switch 1000 coroutine contest 1000000 times, cost time: 0 s, clock time: 282 ms, avg: 282 ns -remove 1000 coroutine, cost time: 0 s, clock time: 2 ms, avg: 2000 ns - -###################### context coroutine (stack using default allocator[mmap]) ################### -########## Cmd: sample/sample_stress_test_coroutine 10000 1000 200 -allocate 10000 coroutine, cost time: 0 s, clock time: 2 ms, avg: 200 ns -create 10000 coroutine, cost time: 0 s, clock time: 74 ms, avg: 7400 ns -switch 10000 coroutine contest 10000000 times, cost time: 4 s, clock time: 3407 ms, avg: 340 ns -remove 10000 coroutine, cost time: 0 s, clock time: 30 ms, avg: 3000 ns -########## Cmd: sample/sample_stress_test_coroutine 1000 1000 2048 +create 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 62 ns +switch 1000 coroutine contest 1000000 times, cost time: 0 s, clock time: 65 ms, avg: 65 ns +remove 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 41 ns +### Round: 3 ### allocate 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 0 ns -create 1000 coroutine, cost time: 0 s, clock time: 8 ms, avg: 8000 ns -switch 1000 coroutine contest 1000000 times, cost time: 0 s, clock time: 223 ms, avg: 223 ns -remove 1000 coroutine, cost time: 0 s, clock time: 4 ms, avg: 4000 ns - -###################### context coroutine (stack using malloc/free [ptmalloc]) ################### -########## Cmd: sample/sample_stress_test_coroutine_malloc 10000 1000 200 -allocate 10000 coroutine, cost time: 0 s, clock time: 6 ms, avg: 600 ns -create 10000 coroutine, cost time: 0 s, clock time: 81 ms, avg: 8100 ns -switch 10000 coroutine contest 10000000 times, cost time: 4 s, clock time: 3809 ms, avg: 380 ns -remove 10000 coroutine, cost time: 0 s, clock time: 26 ms, avg: 2600 ns -########## Cmd: sample/sample_stress_test_coroutine_malloc 1000 1000 2048 +create 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 62 ns +switch 1000 coroutine contest 1000000 times, cost time: 0 s, clock time: 65 ms, avg: 65 ns +remove 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 40 ns +### Round: 4 ### allocate 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 0 ns -create 1000 coroutine, cost time: 0 s, clock time: 8 ms, avg: 8000 ns -switch 1000 coroutine contest 1000000 times, cost time: 0 s, clock time: 248 ms, avg: 248 ns -remove 1000 coroutine, cost time: 0 s, clock time: 4 ms, avg: 4000 ns - +create 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 61 ns +switch 1000 coroutine contest 1000000 times, cost time: 0 s, clock time: 65 ms, avg: 65 ns +remove 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 38 ns +### Round: 5 ### +allocate 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 0 ns +create 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 61 ns +switch 1000 coroutine contest 1000000 times, cost time: 0 s, clock time: 65 ms, avg: 65 ns +remove 1000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 56 ns +###################### context coroutine (stack using stack pool) ################### +########## Cmd: sample/libcopp_sample_benchmark_coroutine_stack_pool 1 1000000 16 +### Round: 1 ### +allocate 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 611 ns +create 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 17943 ns +switch 1 coroutine contest 1000000 times, cost time: 0 s, clock time: 48 ms, avg: 48 ns +remove 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 9548 ns +### Round: 2 ### +allocate 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 391 ns +create 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 1944 ns +switch 1 coroutine contest 1000000 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 2524 ns +### Round: 3 ### +allocate 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 291 ns +create 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 1132 ns +switch 1 coroutine contest 1000000 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 1592 ns +### Round: 4 ### +allocate 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 311 ns +create 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 1082 ns +switch 1 coroutine contest 1000000 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 1022 ns +### Round: 5 ### +allocate 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 70 ns +create 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 541 ns +switch 1 coroutine contest 1000000 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1 coroutine, cost time: 0 s, clock time: 0 ms, avg: 4839 ns +###################### std callable - create generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_create_generator 30000 100 64 +### Round: 1 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 9 ms, avg: 322 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 312 ms, avg: 103 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 29 ns +### Round: 2 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 103 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 305 ms, avg: 100 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 33 ns +### Round: 3 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 110 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 292 ms, avg: 96 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 36 ns +### Round: 4 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 103 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 324 ms, avg: 107 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 34 ns +### Round: 5 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 111 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 324 ms, avg: 106 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 32 ns +###################### std callable - create generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_create_generator 1000 1000 2048 +### Round: 1 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 302 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 107 ms, avg: 106 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 34 ns +### Round: 2 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 99 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 110 ms, avg: 110 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 33 ns +### Round: 3 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 100 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 108 ms, avg: 108 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 33 ns +### Round: 4 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 98 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 108 ms, avg: 108 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 34 ns +### Round: 5 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 100 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 107 ms, avg: 107 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 32 ns +###################### std callable - create generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_create_generator 1 1000000 16 +### Round: 1 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1172 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 1 s, clock time: 91 ms, avg: 91 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 4579 ns +### Round: 2 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 291 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 91 ms, avg: 91 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 3397 ns +### Round: 3 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 371 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 90 ms, avg: 90 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 3226 ns +### Round: 4 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 240 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 90 ms, avg: 90 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 2785 ns +### Round: 5 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 361 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 90 ms, avg: 90 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 1904 ns +###################### std callable - create generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_create_generator_no_trivial 30000 100 64 +### Round: 1 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 9 ms, avg: 321 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 328 ms, avg: 108 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 29 ns +### Round: 2 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 101 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 349 ms, avg: 115 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 36 ns +### Round: 3 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 109 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 342 ms, avg: 112 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 34 ns +### Round: 4 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 105 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 344 ms, avg: 113 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 33 ns +### Round: 5 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 106 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 336 ms, avg: 111 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 30 ns +###################### std callable - create generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_create_generator_no_trivial 1000 1000 2048 +### Round: 1 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 301 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 109 ms, avg: 109 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +### Round: 2 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 108 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 109 ms, avg: 109 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 60 ns +### Round: 3 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 109 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 108 ms, avg: 108 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 30 ns +### Round: 4 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 99 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 109 ms, avg: 109 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 32 ns +### Round: 5 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 99 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 108 ms, avg: 108 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +###################### std callable - create generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_create_generator_no_trivial 1 1000000 16 +### Round: 1 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1222 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 105 ms, avg: 105 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 3547 ns +### Round: 2 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 311 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 105 ms, avg: 105 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 2414 ns +### Round: 3 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 211 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 1 s, clock time: 104 ms, avg: 104 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 2915 ns +### Round: 4 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 381 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 104 ms, avg: 104 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 1974 ns +### Round: 5 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 210 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 105 ms, avg: 105 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 2965 ns +###################### std callable - recursive ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_recursive 30000 100 64 +### Round: 1 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 5 ms, avg: 189 ns +resume 30000 callable(s) and generator(s) for 3000000 times, cost time: 0 s, clock time: 212 ms, avg: 70 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 27 ns +### Round: 2 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 215 ms, avg: 7184 ns +resume 30000 callable(s) and generator(s) for 3000000 times, cost time: 0 s, clock time: 0 ms, avg: 0 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 34 ns +### Round: 3 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 217 ms, avg: 7258 ns +resume 30000 callable(s) and generator(s) for 3000000 times, cost time: 0 s, clock time: 0 ms, avg: 0 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 40 ns +### Round: 4 ### +create 30000 callable(s) and generator(s), cost time: 1 s, clock time: 219 ms, avg: 7312 ns +resume 30000 callable(s) and generator(s) for 3000000 times, cost time: 0 s, clock time: 0 ms, avg: 0 ns +remove 30000 callable(s), cost time: 0 s, clock time: 2 ms, avg: 83 ns +### Round: 5 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 214 ms, avg: 7147 ns +resume 30000 callable(s) and generator(s) for 3000000 times, cost time: 0 s, clock time: 0 ms, avg: 0 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 55 ns +###################### std callable - recursive ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_recursive 1000 1000 2048 +### Round: 1 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 185 ns +resume 1000 callable(s) and generator(s) for 1000000 times, cost time: 0 s, clock time: 75 ms, avg: 75 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 46 ns +### Round: 2 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 81 ms, avg: 81102 ns +resume 1000 callable(s) and generator(s) for 1000000 times, cost time: 0 s, clock time: 0 ms, avg: 0 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 40 ns +### Round: 3 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 80 ms, avg: 80520 ns +resume 1000 callable(s) and generator(s) for 1000000 times, cost time: 0 s, clock time: 0 ms, avg: 0 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 41 ns +### Round: 4 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 81 ms, avg: 81838 ns +resume 1000 callable(s) and generator(s) for 1000000 times, cost time: 0 s, clock time: 0 ms, avg: 0 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 45 ns +### Round: 5 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 81 ms, avg: 81328 ns +resume 1000 callable(s) and generator(s) for 1000000 times, cost time: 0 s, clock time: 0 ms, avg: 0 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 43 ns +###################### std callable - recursive ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_recursive 1 10000 16 +### Round: 1 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 962 ns +resume 1 callable(s) and generator(s) for 10000 times, cost time: 0 s, clock time: 2 ms, avg: 281 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 1573 ns +### Round: 2 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 845252 ns +resume 1 callable(s) and generator(s) for 10000 times, cost time: 0 s, clock time: 0 ms, avg: 0 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 351 ns +### Round: 3 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 875429 ns +resume 1 callable(s) and generator(s) for 10000 times, cost time: 0 s, clock time: 0 ms, avg: 0 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 331 ns +### Round: 4 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 827260 ns +resume 1 callable(s) and generator(s) for 10000 times, cost time: 0 s, clock time: 0 ms, avg: 0 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 311 ns +### Round: 5 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 849541 ns +resume 1 callable(s) and generator(s) for 10000 times, cost time: 0 s, clock time: 0 ms, avg: 0 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 250 ns +###################### std callable - reuse channel generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_channel_generator 30000 100 64 +### Round: 1 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 7 ms, avg: 264 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 101 ms, avg: 33 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 53 ns +### Round: 2 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 2 ms, avg: 76 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 103 ms, avg: 34 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 53 ns +### Round: 3 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 2 ms, avg: 77 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 103 ms, avg: 34 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 53 ns +### Round: 4 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 2 ms, avg: 77 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 103 ms, avg: 34 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 53 ns +### Round: 5 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 2 ms, avg: 76 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 103 ms, avg: 34 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 52 ns +###################### std callable - reuse channel generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_channel_generator 1000 1000 2048 +### Round: 1 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 256 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 33 ms, avg: 33 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 55 ns +### Round: 2 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 77 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 33 ms, avg: 33 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 52 ns +### Round: 3 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 72 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 33 ms, avg: 33 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 54 ns +### Round: 4 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 105 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 33 ms, avg: 33 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 53 ns +### Round: 5 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 83 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 33 ms, avg: 33 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 54 ns +###################### std callable - reuse channel generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_channel_generator 1 1000000 16 +### Round: 1 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 962 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 33 ms, avg: 33 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 2234 ns +### Round: 2 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 361 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 33 ms, avg: 33 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 921 ns +### Round: 3 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 341 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 33 ms, avg: 33 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 1202 ns +### Round: 4 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 321 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 33 ms, avg: 33 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 711 ns +### Round: 5 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 301 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 33 ms, avg: 33 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 942 ns +###################### std callable - reuse channel generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_channel_generator_no_trivial 30000 100 64 +### Round: 1 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 8 ms, avg: 272 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 144 ms, avg: 47 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 35 ns +### Round: 2 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 2 ms, avg: 78 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 144 ms, avg: 47 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 32 ns +### Round: 3 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 2 ms, avg: 80 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 146 ms, avg: 48 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 28 ns +### Round: 4 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 2 ms, avg: 77 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 146 ms, avg: 48 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 34 ns +### Round: 5 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 2 ms, avg: 81 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 147 ms, avg: 48 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 28 ns +###################### std callable - reuse channel generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_channel_generator_no_trivial 1000 1000 2048 +### Round: 1 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 254 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 32 ns +### Round: 2 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 75 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 48 ms, avg: 47 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 41 ns +### Round: 3 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 75 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 29 ns +### Round: 4 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 84 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 48 ms, avg: 48 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +### Round: 5 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 75 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 30 ns +###################### std callable - reuse channel generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_channel_generator_no_trivial 1 1000000 16 +### Round: 1 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 971 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 3387 ns +### Round: 2 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 341 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 1453 ns +### Round: 3 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 201 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 1663 ns +### Round: 4 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 280 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 2334 ns +### Round: 5 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 290 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 1353 ns +###################### std callable - reuse generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_generator 30000 100 64 +### Round: 1 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 9 ms, avg: 331 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 146 ms, avg: 48 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 32 ns +### Round: 2 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 107 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 152 ms, avg: 50 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 33 ns +### Round: 3 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 103 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 146 ms, avg: 48 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 29 ns +### Round: 4 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 103 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 150 ms, avg: 49 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 32 ns +### Round: 5 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 103 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 146 ms, avg: 48 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 30 ns +###################### std callable - reuse generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_generator 1000 1000 2048 +### Round: 1 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 315 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 30 ns +### Round: 2 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 98 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 48 ms, avg: 48 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 30 ns +### Round: 3 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 100 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 48 ms, avg: 47 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +### Round: 4 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 98 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 48 ms, avg: 48 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 30 ns +### Round: 5 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 99 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +###################### std callable - reuse generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_generator 1 1000000 16 +### Round: 1 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1022 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 49 ms, avg: 49 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 3456 ns +### Round: 2 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1013 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 1 s, clock time: 48 ms, avg: 48 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 1613 ns +### Round: 3 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 480 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 49 ms, avg: 49 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 2124 ns +### Round: 4 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 701 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 48 ms, avg: 48 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 2735 ns +### Round: 5 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 792 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 49 ms, avg: 49 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 3216 ns +###################### std callable - reuse generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_generator_no_trivial 30000 100 64 +### Round: 1 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 9 ms, avg: 319 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 172 ms, avg: 56 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 29 ns +### Round: 2 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 103 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 183 ms, avg: 60 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 34 ns +### Round: 3 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 102 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 171 ms, avg: 56 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 28 ns +### Round: 4 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 103 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 184 ms, avg: 60 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 33 ns +### Round: 5 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 101 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 172 ms, avg: 56 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 28 ns +###################### std callable - reuse generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_generator_no_trivial 1000 1000 2048 +### Round: 1 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 297 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 55 ms, avg: 55 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +### Round: 2 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 97 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 55 ms, avg: 55 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +### Round: 3 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 97 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 55 ms, avg: 55 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 29 ns +### Round: 4 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 96 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 56 ms, avg: 55 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 30 ns +### Round: 5 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 98 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 55 ms, avg: 55 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +###################### std callable - reuse generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_generator_no_trivial 1 1000000 16 +### Round: 1 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1021 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 56 ms, avg: 56 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 2053 ns +### Round: 2 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 280 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 55 ms, avg: 55 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 2134 ns +### Round: 3 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 260 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 71 ms, avg: 71 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 1643 ns +### Round: 4 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 161 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 54 ms, avg: 54 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 2515 ns +### Round: 5 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 371 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 54 ms, avg: 54 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 2464 ns +###################### std callable - reuse lightweight generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_lightweight_generator 30000 100 64 +### Round: 1 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 8 ms, avg: 296 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 157 ms, avg: 51 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 30 ns +### Round: 2 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 105 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 159 ms, avg: 52 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 38 ns +### Round: 3 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 121 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 161 ms, avg: 53 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 41 ns +### Round: 4 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 130 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 162 ms, avg: 53 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 53 ns +### Round: 5 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 4 ms, avg: 152 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 164 ms, avg: 54 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 45 ns +###################### std callable - reuse lightweight generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_lightweight_generator 1000 1000 2048 +### Round: 1 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 290 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 50 ms, avg: 50 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 33 ns +### Round: 2 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 102 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 50 ms, avg: 50 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +### Round: 3 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 103 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 50 ms, avg: 50 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 32 ns +### Round: 4 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 102 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 50 ms, avg: 50 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 34 ns +### Round: 5 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 128 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 50 ms, avg: 50 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +###################### std callable - reuse lightweight generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_lightweight_generator 1 1000000 16 +### Round: 1 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1052 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 49 ms, avg: 49 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 4248 ns +### Round: 2 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 682 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 49 ms, avg: 49 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 4528 ns +### Round: 3 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 862 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 49 ms, avg: 49 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 1763 ns +### Round: 4 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 481 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 49 ms, avg: 49 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 1473 ns +### Round: 5 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 712 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 49 ms, avg: 49 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 3297 ns +###################### std callable - reuse lightweight generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_lightweight_generator_no_trivial 30000 100 64 +### Round: 1 ### +create 30000 callable(s) and generator(s), cost time: 1 s, clock time: 9 ms, avg: 306 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 179 ms, avg: 59 ns +remove 30000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 28 ns +### Round: 2 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 102 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 184 ms, avg: 60 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 38 ns +### Round: 3 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 123 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 187 ms, avg: 61 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 40 ns +### Round: 4 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 128 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 194 ms, avg: 64 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 43 ns +### Round: 5 ### +create 30000 callable(s) and generator(s), cost time: 0 s, clock time: 4 ms, avg: 143 ns +resume 30000 callable(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 196 ms, avg: 64 ns +remove 30000 callable(s), cost time: 0 s, clock time: 1 ms, avg: 39 ns +###################### std callable - reuse lightweight generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_lightweight_generator_no_trivial 1000 1000 2048 +### Round: 1 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 296 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 1 s, clock time: 58 ms, avg: 58 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 33 ns +### Round: 2 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 99 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 58 ms, avg: 58 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 33 ns +### Round: 3 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 114 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 58 ms, avg: 58 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 33 ns +### Round: 4 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 103 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 58 ms, avg: 58 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +### Round: 5 ### +create 1000 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 104 ns +resume 1000 callable(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 58 ms, avg: 58 ns +remove 1000 callable(s), cost time: 0 s, clock time: 0 ms, avg: 32 ns +###################### std callable - reuse lightweight generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_callable_reuse_lightweight_generator_no_trivial 1 1000000 16 +### Round: 1 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1102 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 55 ms, avg: 55 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 4458 ns +### Round: 2 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 420 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 55 ms, avg: 55 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 2895 ns +### Round: 3 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 280 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 55 ms, avg: 55 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 561 ns +### Round: 4 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 100 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 55 ms, avg: 55 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 421 ns +### Round: 5 ### +create 1 callable(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 110 ns +resume 1 callable(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 55 ms, avg: 55 ns +remove 1 callable(s), cost time: 0 s, clock time: 0 ms, avg: 1583 ns +###################### std task - create generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_task_create_generator 30000 100 64 +### Round: 1 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 11 ms, avg: 395 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 352 ms, avg: 116 ns +remove 30000 task(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +### Round: 2 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 129 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 415 ms, avg: 137 ns +remove 30000 task(s), cost time: 0 s, clock time: 1 ms, avg: 45 ns +### Round: 3 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 120 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 359 ms, avg: 118 ns +remove 30000 task(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +### Round: 4 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 127 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 419 ms, avg: 138 ns +remove 30000 task(s), cost time: 0 s, clock time: 1 ms, avg: 44 ns +### Round: 5 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 119 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 354 ms, avg: 117 ns +remove 30000 task(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +###################### std task - create generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_task_create_generator 1000 1000 2048 +### Round: 1 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 369 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 110 ms, avg: 110 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 35 ns +### Round: 2 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 183 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 117 ms, avg: 117 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 35 ns +### Round: 3 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 109 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 116 ms, avg: 116 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 33 ns +### Round: 4 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 109 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 116 ms, avg: 115 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 36 ns +### Round: 5 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 119 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 1 s, clock time: 116 ms, avg: 116 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 33 ns +###################### std task - create generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_task_create_generator 1 1000000 16 +### Round: 1 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 6833 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 90 ms, avg: 90 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 3837 ns +### Round: 2 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 612 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 92 ms, avg: 92 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 3456 ns +### Round: 3 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1053 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 90 ms, avg: 90 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 2083 ns +### Round: 4 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 601 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 90 ms, avg: 90 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 2865 ns +### Round: 5 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1122 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 91 ms, avg: 91 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 3376 ns +###################### std task - create generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_task_create_generator_no_trivial 30000 100 64 +### Round: 1 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 11 ms, avg: 397 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 328 ms, avg: 108 ns +remove 30000 task(s), cost time: 0 s, clock time: 1 ms, avg: 40 ns +### Round: 2 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 4 ms, avg: 135 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 373 ms, avg: 123 ns +remove 30000 task(s), cost time: 0 s, clock time: 1 ms, avg: 61 ns +### Round: 3 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 128 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 348 ms, avg: 115 ns +remove 30000 task(s), cost time: 0 s, clock time: 1 ms, avg: 40 ns +### Round: 4 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 4 ms, avg: 151 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 409 ms, avg: 135 ns +remove 30000 task(s), cost time: 0 s, clock time: 2 ms, avg: 87 ns +### Round: 5 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 4 ms, avg: 154 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 346 ms, avg: 114 ns +remove 30000 task(s), cost time: 0 s, clock time: 1 ms, avg: 40 ns +###################### std task - create generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_task_create_generator_no_trivial 1000 1000 2048 +### Round: 1 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 400 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 111 ms, avg: 111 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 43 ns +### Round: 2 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 128 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 112 ms, avg: 111 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 45 ns +### Round: 3 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 138 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 112 ms, avg: 111 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 41 ns +### Round: 4 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 105 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 112 ms, avg: 112 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 47 ns +### Round: 5 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 103 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 111 ms, avg: 111 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 42 ns +###################### std task - create generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_task_create_generator_no_trivial 1 1000000 16 +### Round: 1 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 6252 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 1 s, clock time: 104 ms, avg: 104 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 5510 ns +### Round: 2 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1212 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 104 ms, avg: 104 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 3386 ns +### Round: 3 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1182 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 104 ms, avg: 104 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 3767 ns +### Round: 4 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 922 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 104 ms, avg: 104 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 4618 ns +### Round: 5 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1503 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 107 ms, avg: 107 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 3376 ns +###################### std task - reuse generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_task_reuse_generator 30000 100 64 +### Round: 1 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 11 ms, avg: 398 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 146 ms, avg: 48 ns +remove 30000 task(s), cost time: 0 s, clock time: 0 ms, avg: 32 ns +### Round: 2 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 126 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 187 ms, avg: 62 ns +remove 30000 task(s), cost time: 0 s, clock time: 1 ms, avg: 45 ns +### Round: 3 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 121 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 151 ms, avg: 50 ns +remove 30000 task(s), cost time: 0 s, clock time: 0 ms, avg: 33 ns +### Round: 4 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 4 ms, avg: 134 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 185 ms, avg: 61 ns +remove 30000 task(s), cost time: 0 s, clock time: 1 ms, avg: 47 ns +### Round: 5 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 3 ms, avg: 128 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 153 ms, avg: 50 ns +remove 30000 task(s), cost time: 0 s, clock time: 0 ms, avg: 32 ns +###################### std task - reuse generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_task_reuse_generator 1000 1000 2048 +### Round: 1 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 370 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 48 ms, avg: 48 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 34 ns +### Round: 2 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 109 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 49 ms, avg: 49 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 35 ns +### Round: 3 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 105 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 31 ns +### Round: 4 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 108 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 49 ms, avg: 49 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 34 ns +### Round: 5 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 105 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 47 ms, avg: 47 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 33 ns +###################### std task - reuse generator - trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_task_reuse_generator 1 1000000 16 +### Round: 1 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 6963 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 49 ms, avg: 49 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 4038 ns +### Round: 2 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1593 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 48 ms, avg: 48 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 2806 ns +### Round: 3 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 881 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 48 ms, avg: 48 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 1713 ns +### Round: 4 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1333 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 48 ms, avg: 48 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 1263 ns +### Round: 5 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 371 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 48 ms, avg: 48 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 2485 ns +###################### std task - reuse generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_task_reuse_generator_no_trivial 30000 100 64 +### Round: 1 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 12 ms, avg: 404 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 1 s, clock time: 170 ms, avg: 56 ns +remove 30000 task(s), cost time: 0 s, clock time: 1 ms, avg: 40 ns +### Round: 2 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 4 ms, avg: 137 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 224 ms, avg: 74 ns +remove 30000 task(s), cost time: 0 s, clock time: 1 ms, avg: 62 ns +### Round: 3 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 4 ms, avg: 135 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 188 ms, avg: 62 ns +remove 30000 task(s), cost time: 0 s, clock time: 1 ms, avg: 43 ns +### Round: 4 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 4 ms, avg: 147 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 233 ms, avg: 77 ns +remove 30000 task(s), cost time: 0 s, clock time: 2 ms, avg: 73 ns +### Round: 5 ### +create 30000 task(s) and generator(s), cost time: 0 s, clock time: 4 ms, avg: 155 ns +resume 30000 task(s) and generator(s) for 3030000 times, cost time: 0 s, clock time: 187 ms, avg: 61 ns +remove 30000 task(s), cost time: 0 s, clock time: 1 ms, avg: 45 ns +###################### std task - reuse generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_task_reuse_generator_no_trivial 1000 1000 2048 +### Round: 1 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 385 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 56 ms, avg: 56 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 54 ns +### Round: 2 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 138 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 57 ms, avg: 57 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 45 ns +### Round: 3 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 128 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 1 s, clock time: 55 ms, avg: 55 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 41 ns +### Round: 4 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 105 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 57 ms, avg: 57 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 47 ns +### Round: 5 ### +create 1000 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 104 ns +resume 1000 task(s) and generator(s) for 1001000 times, cost time: 0 s, clock time: 55 ms, avg: 55 ns +remove 1000 task(s), cost time: 0 s, clock time: 0 ms, avg: 41 ns +###################### std task - reuse generator - no trivial ################### +########## Cmd: sample/libcopp_sample_benchmark_std_couroutine_task_reuse_generator_no_trivial 1 1000000 16 +### Round: 1 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 6492 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 53 ms, avg: 53 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 4328 ns +### Round: 2 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1032 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 54 ms, avg: 54 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 3005 ns +### Round: 3 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 1182 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 54 ms, avg: 54 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 3276 ns +### Round: 4 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 952 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 53 ms, avg: 53 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 2445 ns +### Round: 5 ### +create 1 task(s) and generator(s), cost time: 0 s, clock time: 0 ms, avg: 331 ns +resume 1 task(s) and generator(s) for 1000001 times, cost time: 0 s, clock time: 53 ms, avg: 53 ns +remove 1 task(s), cost time: 0 s, clock time: 0 ms, avg: 3256 ns +###################### context coroutine (stack using default allocator[mmap]) ################### +########## Cmd: sample/libcopp_sample_benchmark_task 30000 100 64 +create 30000 task, cost time: 0 s, clock time: 235 ms, avg: 7845 ns +switch 30000 tasks 3000000 times, cost time: 1 s, clock time: 419 ms, avg: 139 ns +remove 30000 tasks, cost time: 0 s, clock time: 187 ms, avg: 6238 ns +###################### context coroutine (stack using default allocator[mmap]) ################### +########## Cmd: sample/libcopp_sample_benchmark_task 1000 1000 2048 +create 1000 task, cost time: 0 s, clock time: 8 ms, avg: 8043 ns +switch 1000 tasks 1000000 times, cost time: 0 s, clock time: 78 ms, avg: 78 ns +remove 1000 tasks, cost time: 0 s, clock time: 6 ms, avg: 6826 ns +###################### context coroutine (stack using default allocator[mmap]) ################### +########## Cmd: sample/libcopp_sample_benchmark_task 1 1000000 16 +create 1 task, cost time: 0 s, clock time: 0 ms, avg: 26550 ns +switch 1 tasks 1000000 times, cost time: 0 s, clock time: 65 ms, avg: 65 ns +remove 1 tasks, cost time: 0 s, clock time: 0 ms, avg: 24576 ns +###################### task (stack using malloc/free) ################### +########## Cmd: sample/libcopp_sample_benchmark_task_malloc 30000 100 64 +create 30000 task, cost time: 0 s, clock time: 72 ms, avg: 2429 ns +switch 30000 tasks 3000000 times, cost time: 0 s, clock time: 347 ms, avg: 115 ns +remove 30000 tasks, cost time: 0 s, clock time: 10 ms, avg: 362 ns +###################### task (stack using malloc/free) ################### +########## Cmd: sample/libcopp_sample_benchmark_task_malloc 1000 1000 2048 +create 1000 task, cost time: 0 s, clock time: 6 ms, avg: 6296 ns +switch 1000 tasks 1000000 times, cost time: 0 s, clock time: 75 ms, avg: 75 ns +remove 1000 tasks, cost time: 0 s, clock time: 5 ms, avg: 5970 ns +###################### task (stack using malloc/free) ################### +########## Cmd: sample/libcopp_sample_benchmark_task_malloc 1 1000000 16 +create 1 task, cost time: 0 s, clock time: 0 ms, avg: 13475 ns +switch 1 tasks 1000000 times, cost time: 1 s, clock time: 65 ms, avg: 65 ns +remove 1 tasks, cost time: 0 s, clock time: 0 ms, avg: 9798 ns ###################### task (stack using memory pool) ################### -########## Cmd: sample/sample_stress_test_task_mem_pool 10000 1000 200 -create 10000 task, cost time: 0 s, clock time: 46 ms, avg: 4600 ns -switch 10000 tasks 10000000 times, cost time: 5 s, clock time: 4914 ms, avg: 491 ns -remove 10000 tasks, cost time: 0 s, clock time: 1 ms, avg: 100 ns -########## Cmd: sample/sample_stress_test_task_mem_pool 1000 1000 2048 -create 1000 task, cost time: 0 s, clock time: 6 ms, avg: 6000 ns -switch 1000 tasks 1000000 times, cost time: 1 s, clock time: 336 ms, avg: 336 ns -remove 1000 tasks, cost time: 0 s, clock time: 0 ms, avg: 0 ns - -###################### task (stack using default allocator[mmap]) ################### -########## Cmd: sample/sample_stress_test_task 10000 1000 200 -create 10000 task, cost time: 0 s, clock time: 78 ms, avg: 7800 ns -switch 10000 tasks 10000000 times, cost time: 5 s, clock time: 5134 ms, avg: 513 ns -remove 10000 tasks, cost time: 0 s, clock time: 34 ms, avg: 3400 ns -########## Cmd: sample/sample_stress_test_task 1000 1000 2048 -create 1000 task, cost time: 0 s, clock time: 8 ms, avg: 8000 ns -switch 1000 tasks 1000000 times, cost time: 0 s, clock time: 330 ms, avg: 330 ns -remove 1000 tasks, cost time: 0 s, clock time: 4 ms, avg: 4000 ns - -###################### task (stack using malloc/free [ptmalloc]) ################### -########## Cmd: sample/sample_stress_test_task_malloc 10000 1000 200 -create 10000 task, cost time: 0 s, clock time: 73 ms, avg: 7300 ns -switch 10000 tasks 10000000 times, cost time: 5 s, clock time: 4803 ms, avg: 480 ns -remove 10000 tasks, cost time: 0 s, clock time: 31 ms, avg: 3100 ns -########## Cmd: sample/sample_stress_test_task_malloc 1000 1000 2048 -create 1000 task, cost time: 0 s, clock time: 9 ms, avg: 9000 ns -switch 1000 tasks 1000000 times, cost time: 0 s, clock time: 335 ms, avg: 335 ns -remove 1000 tasks, cost time: 1 s, clock time: 4 ms, avg: 4000 ns - +########## Cmd: sample/libcopp_sample_benchmark_task_mem_pool 30000 100 64 +create 30000 task, cost time: 0 s, clock time: 3 ms, avg: 116 ns +switch 30000 tasks 3000000 times, cost time: 0 s, clock time: 420 ms, avg: 140 ns +remove 30000 tasks, cost time: 0 s, clock time: 1 ms, avg: 61 ns +###################### task (stack using memory pool) ################### +########## Cmd: sample/libcopp_sample_benchmark_task_mem_pool 1000 1000 2048 +create 1000 task, cost time: 0 s, clock time: 0 ms, avg: 137 ns +switch 1000 tasks 1000000 times, cost time: 0 s, clock time: 70 ms, avg: 70 ns +remove 1000 tasks, cost time: 0 s, clock time: 0 ms, avg: 57 ns +###################### task (stack using memory pool) ################### +########## Cmd: sample/libcopp_sample_benchmark_task_mem_pool 1 1000000 16 +create 1 task, cost time: 0 s, clock time: 0 ms, avg: 11001 ns +switch 1 tasks 1000000 times, cost time: 0 s, clock time: 64 ms, avg: 64 ns +remove 1 tasks, cost time: 0 s, clock time: 0 ms, avg: 5150 ns +###################### task (stack using stack pool) ################### +########## Cmd: sample/libcopp_sample_benchmark_task_stack_pool 30000 100 64 +### Round: 1 ### +create 30000 task, cost time: 1 s, clock time: 231 ms, avg: 7712 ns +switch 30000 tasks 3000000 times, cost time: 0 s, clock time: 417 ms, avg: 139 ns +remove 30000 tasks, cost time: 0 s, clock time: 3 ms, avg: 107 ns +### Round: 2 ### +create 30000 task, cost time: 0 s, clock time: 2 ms, avg: 97 ns +switch 30000 tasks 3000000 times, cost time: 1 s, clock time: 429 ms, avg: 143 ns +remove 30000 tasks, cost time: 0 s, clock time: 2 ms, avg: 75 ns +### Round: 3 ### +create 30000 task, cost time: 0 s, clock time: 3 ms, avg: 101 ns +switch 30000 tasks 3000000 times, cost time: 0 s, clock time: 444 ms, avg: 148 ns +remove 30000 tasks, cost time: 0 s, clock time: 2 ms, avg: 68 ns +### Round: 4 ### +create 30000 task, cost time: 0 s, clock time: 2 ms, avg: 97 ns +switch 30000 tasks 3000000 times, cost time: 0 s, clock time: 449 ms, avg: 149 ns +remove 30000 tasks, cost time: 0 s, clock time: 1 ms, avg: 65 ns +### Round: 5 ### +create 30000 task, cost time: 0 s, clock time: 3 ms, avg: 107 ns +switch 30000 tasks 3000000 times, cost time: 1 s, clock time: 445 ms, avg: 148 ns +remove 30000 tasks, cost time: 0 s, clock time: 1 ms, avg: 65 ns +###################### task (stack using stack pool) ################### +########## Cmd: sample/libcopp_sample_benchmark_task_stack_pool 1000 1000 2048 +### Round: 1 ### +create 1000 task, cost time: 0 s, clock time: 10 ms, avg: 10436 ns +switch 1000 tasks 1000000 times, cost time: 0 s, clock time: 79 ms, avg: 79 ns +remove 1000 tasks, cost time: 0 s, clock time: 0 ms, avg: 105 ns +### Round: 2 ### +create 1000 task, cost time: 0 s, clock time: 0 ms, avg: 100 ns +switch 1000 tasks 1000000 times, cost time: 0 s, clock time: 78 ms, avg: 78 ns +remove 1000 tasks, cost time: 0 s, clock time: 0 ms, avg: 59 ns +### Round: 3 ### +create 1000 task, cost time: 0 s, clock time: 0 ms, avg: 95 ns +switch 1000 tasks 1000000 times, cost time: 0 s, clock time: 78 ms, avg: 78 ns +remove 1000 tasks, cost time: 0 s, clock time: 0 ms, avg: 63 ns +### Round: 4 ### +create 1000 task, cost time: 0 s, clock time: 0 ms, avg: 95 ns +switch 1000 tasks 1000000 times, cost time: 0 s, clock time: 79 ms, avg: 79 ns +remove 1000 tasks, cost time: 0 s, clock time: 0 ms, avg: 61 ns +### Round: 5 ### +create 1000 task, cost time: 0 s, clock time: 0 ms, avg: 95 ns +switch 1000 tasks 1000000 times, cost time: 0 s, clock time: 78 ms, avg: 78 ns +remove 1000 tasks, cost time: 0 s, clock time: 0 ms, avg: 62 ns +###################### task (stack using stack pool) ################### +########## Cmd: sample/libcopp_sample_benchmark_task_stack_pool 1 1000000 16 +### Round: 1 ### +create 1 task, cost time: 0 s, clock time: 0 ms, avg: 20980 ns +switch 1 tasks 1000000 times, cost time: 0 s, clock time: 65 ms, avg: 65 ns +remove 1 tasks, cost time: 0 s, clock time: 0 ms, avg: 8415 ns +### Round: 2 ### +create 1 task, cost time: 0 s, clock time: 0 ms, avg: 6012 ns +switch 1 tasks 1000000 times, cost time: 0 s, clock time: 64 ms, avg: 64 ns +remove 1 tasks, cost time: 0 s, clock time: 0 ms, avg: 2766 ns +### Round: 3 ### +create 1 task, cost time: 0 s, clock time: 0 ms, avg: 1323 ns +switch 1 tasks 1000000 times, cost time: 0 s, clock time: 64 ms, avg: 64 ns +remove 1 tasks, cost time: 0 s, clock time: 0 ms, avg: 1223 ns +### Round: 4 ### +create 1 task, cost time: 0 s, clock time: 0 ms, avg: 822 ns +switch 1 tasks 1000000 times, cost time: 0 s, clock time: 64 ms, avg: 64 ns +remove 1 tasks, cost time: 0 s, clock time: 0 ms, avg: 4799 ns +### Round: 5 ### +create 1 task, cost time: 0 s, clock time: 0 ms, avg: 2044 ns +switch 1 tasks 1000000 times, cost time: 0 s, clock time: 64 ms, avg: 64 ns +remove 1 tasks, cost time: 0 s, clock time: 0 ms, avg: 4648 ns diff --git a/docs/reports/windows_benchmark_report.txt b/docs/reports/windows_benchmark_report.txt index 24e8f7e..265c18b 100755 --- a/docs/reports/windows_benchmark_report.txt +++ b/docs/reports/windows_benchmark_report.txt @@ -1,75 +1,320 @@ ======================================================================================= -Env: Windows 7, Visual Studio 2013 (VC 18) -System: Windows 7 -CPU: AMD Phenom(tm) II X4 830 Processor (800MHz- 2800MHz) -Memory: 8GB DDR3-1333 -CMake Build Type: Release -Run Env => thread number: 1, stack memory cost 2.0GB -Compile Options: /GS /TP /W3 /Zi /Gm- /O2 /Ob2 /GL /EHsc /nologo /D "NDEBUG" +Source: GitHub Actions - job "MinGW Build (windows-latest, ON)" + https://github.com/owent/libcopp/actions/runs/34942431606 +Env: Windows Server (GitHub-hosted windows-latest runner), MinGW-w64 gcc 16.2.0 +System: Windows +CPU: GitHub-hosted runner (4 vCPU) +Memory: 16 GB +CMake Build Type: RelWithDebInfo +Run Env => thread number: 1 +Note: The MSVC (Visual Studio 17 2022) job logs were truncated by GitHub, so results + from the MinGW-w64 windows-latest build are shown here. Each case ran with its + default arguments (100000 coroutines/tasks, 10000000 switch operations). + Binary names are abbreviated (bin/libcopp_sb* = sample_benchmark_*); the category + of each case is described in its "######" header line. +Captured from CI: 2026-09-15 +======================================================================================= -###################### context coroutine (stack using memory pool) ################### -########## Cmd: sample/Release/sample_stress_test_coroutines_mem_pool 10000 1000 200 -allocate 10000 coroutine, cost time: 0 s, clock time: 11 ms, avg: 1100 ns -create 10000 coroutine, cost time: 0 s, clock time: 296 ms, avg: 29600 ns -switch 10000 coroutine contest 10000000 times, cost time: 6 s, clock time: 6359 ms, avg: 635 ns -remove 10000 coroutine, cost time: 1 s, clock time: 209 ms, avg: 20900 ns -########## Cmd: sample/Release/sample_stress_test_coroutines_mem_pool 1000 1000 2048 -allocate 1000 coroutine, cost time: 0 s, clock time: 2 ms, avg: 2000 ns -create 1000 coroutine, cost time: 0 s, clock time: 37 ms, avg: 37000 ns -switch 1000 coroutine contest 1000000 times, cost time: 0 s, clock time: 308 ms, avg: 308 ns -remove 1000 coroutine, cost time: 0 s, clock time: 7 ms, avg: 7000 ns - -###################### context coroutine (stack using default allocator[VirtualAlloc]) ################### -########## Cmd: sample/Release/sample_stress_test_coroutine 10000 1000 200 -allocate 10000 coroutine, cost time: 0 s, clock time: 11 ms, avg: 1100 ns -create 10000 coroutine, cost time: 0 s, clock time: 139 ms, avg: 13900 ns -switch 10000 coroutine contest 10000000 times, cost time: 6 s, clock time: 6251 ms, avg: 625 ns -remove 10000 coroutine, cost time: 0 s, clock time: 21 ms, avg: 2100 ns -########## Cmd: sample/Release/sample_stress_test_coroutine 1000 1000 2048 -allocate 1000 coroutine, cost time: 0 s, clock time: 1 ms, avg: 1000 ns -create 1000 coroutine, cost time: 0 s, clock time: 15 ms, avg: 15000 ns -switch 1000 coroutine contest 1000000 times, cost time: 1 s, clock time: 275 ms, avg: 275 ns -remove 1000 coroutine, cost time: 0 s, clock time: 4 ms, avg: 4000 ns - -###################### context coroutine (stack using malloc/free) ################### -########## Cmd: sample/Release/sample_stress_test_coroutine_malloc 10000 1000 200 -allocate 10000 coroutine, cost time: 0 s, clock time: 12 ms, avg: 1200 ns -create 10000 coroutine, cost time: 0 s, clock time: 228 ms, avg: 22800 ns -switch 10000 coroutine contest 10000000 times, cost time: 6 s, clock time: 6282 ms, avg: 628 ns -remove 10000 coroutine, cost time: 0 s, clock time: 16 ms, avg: 1600 ns -########## Cmd: sample/Release/sample_stress_test_coroutine_malloc 1000 1000 2048 -allocate 1000 coroutine, cost time: 0 s, clock time: 1 ms, avg: 1000 ns -create 1000 coroutine, cost time: 0 s, clock time: 22 ms, avg: 22000 ns -switch 1000 coroutine contest 1000000 times, cost time: 1 s, clock time: 463 ms, avg: 463 ns -remove 1000 coroutine, cost time: 0 s, clock time: 4 ms, avg: 4000 ns - -###################### task (stack using memory pool) ################### -########## Cmd: sample/Release/sample_stress_test_task_mem_pool 10000 1000 200 -create 10000 task, cost time: 0 s, clock time: 249 ms, avg: 24900 ns -switch 10000 tasks 10000000 times, cost time: 9 s, clock time: 8873 ms, avg: 887 ns -remove 10000 tasks, cost time: 0 s, clock time: 4 ms, avg: 400 ns -########## Cmd: sample/Release/sample_stress_test_task_mem_pool 1000 1000 2048 -create 1000 task, cost time: 0 s, clock time: 27 ms, avg: 27000 ns -switch 1000 tasks 1000000 times, cost time: 1 s, clock time: 564 ms, avg: 564 ns -remove 1000 tasks, cost time: 0 s, clock time: 0 ms, avg: 0 ns - -###################### task (stack using default allocator[VirtualAlloc]) ################### -########## Cmd: sample/Release/sample_stress_test_task 10000 1000 200 -create 10000 task, cost time: 0 s, clock time: 167 ms, avg: 16700 ns -switch 10000 tasks 10000000 times, cost time: 9 s, clock time: 9440 ms, avg: 944 ns -remove 10000 tasks, cost time: 0 s, clock time: 29 ms, avg: 2900 ns -########## Cmd: sample/Release/sample_stress_test_task 1000 1000 2048 -create 1000 task, cost time: 0 s, clock time: 18 ms, avg: 18000 ns -switch 1000 tasks 1000000 times, cost time: 1 s, clock time: 515 ms, avg: 515 ns -remove 1000 tasks, cost time: 0 s, clock time: 6 ms, avg: 6000 ns - -###################### task (stack using malloc/free) ################### -########## Cmd: sample/Release/sample_stress_test_task_malloc 10000 1000 200 -create 10000 task, cost time: 0 s, clock time: 335 ms, avg: 33500 ns -switch 10000 tasks 10000000 times, cost time: 10 s, clock time: 10102 ms, avg: 1010 ns -remove 10000 tasks, cost time: 0 s, clock time: 75 ms, avg: 7500 ns -########## Cmd: sample/Release/sample_stress_test_task_malloc 1000 1000 2048 -create 1000 task, cost time: 0 s, clock time: 44 ms, avg: 44000 ns -switch 1000 tasks 1000000 times, cost time: 1 s, clock time: 543 ms, avg: 543 ns -remove 1000 tasks, cost time: 0 s, clock time: 9 ms, avg: 9000 ns - +###################### context coroutine (stack using default allocator[VirtualAlloc]) ################### +########## Cmd: bin/libcopp_sbc.exe +allocate 100000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 2 ns +create 100000 coroutine, cost time: 1 s, clock time: 367 ms, avg: 3679 ns +switch 100000 coroutine contest 10000000 times, cost time: 2 s, clock time: 2190 ms, avg: 219 ns +remove 100000 coroutine, cost time: 0 s, clock time: 241 ms, avg: 2416 ns +###################### context coroutine (stack using malloc/free) ################### +########## Cmd: bin/libcopp_sbcm.exe +allocate 100000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 1 ns +create 100000 coroutine, cost time: 0 s, clock time: 335 ms, avg: 3352 ns +switch 100000 coroutine contest 10000000 times, cost time: 4 s, clock time: 3648 ms, avg: 364 ns +remove 100000 coroutine, cost time: 0 s, clock time: 105 ms, avg: 1057 ns +###################### context coroutine (stack using memory pool) ################### +########## Cmd: bin/libcopp_sbcmp.exe +allocate 100000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 1 ns +create 100000 coroutine, cost time: 0 s, clock time: 10 ms, avg: 107 ns +switch 100000 coroutine contest 10000000 times, cost time: 2 s, clock time: 2195 ms, avg: 219 ns +remove 100000 coroutine, cost time: 0 s, clock time: 60 ms, avg: 604 ns +###################### context coroutine (stack using stack pool) ################### +########## Cmd: bin/libcopp_sbcsp.exe +### Round: 1 ### +allocate 100000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 2 ns +create 100000 coroutine, cost time: 0 s, clock time: 353 ms, avg: 3533 ns +switch 100000 coroutine contest 10000000 times, cost time: 2 s, clock time: 2183 ms, avg: 218 ns +remove 100000 coroutine, cost time: 0 s, clock time: 7 ms, avg: 75 ns +### Round: 2 ### +allocate 100000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 0 ns +create 100000 coroutine, cost time: 0 s, clock time: 8 ms, avg: 87 ns +switch 100000 coroutine contest 10000000 times, cost time: 3 s, clock time: 2181 ms, avg: 218 ns +remove 100000 coroutine, cost time: 0 s, clock time: 7 ms, avg: 73 ns +### Round: 3 ### +allocate 100000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 0 ns +create 100000 coroutine, cost time: 0 s, clock time: 8 ms, avg: 81 ns +switch 100000 coroutine contest 10000000 times, cost time: 2 s, clock time: 2303 ms, avg: 230 ns +remove 100000 coroutine, cost time: 0 s, clock time: 12 ms, avg: 121 ns +### Round: 4 ### +allocate 100000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 0 ns +create 100000 coroutine, cost time: 0 s, clock time: 12 ms, avg: 129 ns +switch 100000 coroutine contest 10000000 times, cost time: 2 s, clock time: 2266 ms, avg: 226 ns +remove 100000 coroutine, cost time: 0 s, clock time: 7 ms, avg: 78 ns +### Round: 5 ### +allocate 100000 coroutine, cost time: 0 s, clock time: 0 ms, avg: 0 ns +create 100000 coroutine, cost time: 0 s, clock time: 8 ms, avg: 82 ns +switch 100000 coroutine contest 10000000 times, cost time: 2 s, clock time: 2195 ms, avg: 219 ns +remove 100000 coroutine, cost time: 0 s, clock time: 9 ms, avg: 90 ns +###################### std callable - create generator - trivial ################### +########## Cmd: bin/libcopp_sbscccg.exe +### Round: 1 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 44 ms, avg: 441 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 164 ns +### Round: 2 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 45 ms, avg: 453 ns +remove 100000 callable(s), cost time: 0 s, clock time: 17 ms, avg: 172 ns +### Round: 3 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 45 ms, avg: 458 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 163 ns +### Round: 4 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 41 ms, avg: 415 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 160 ns +### Round: 5 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 41 ms, avg: 417 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 169 ns +###################### std callable - create generator - no trivial ################### +########## Cmd: bin/libcopp_sbscccgnt.exe +### Round: 1 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 41 ms, avg: 419 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 164 ns +### Round: 2 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 40 ms, avg: 407 ns +remove 100000 callable(s), cost time: 0 s, clock time: 17 ms, avg: 172 ns +### Round: 3 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 42 ms, avg: 425 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 162 ns +### Round: 4 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 45 ms, avg: 453 ns +remove 100000 callable(s), cost time: 0 s, clock time: 17 ms, avg: 177 ns +### Round: 5 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 42 ms, avg: 420 ns +remove 100000 callable(s), cost time: 0 s, clock time: 18 ms, avg: 181 ns +###################### std callable - recursive ################### +########## Cmd: bin/libcopp_sbsccr.exe +### Round: 1 ### +create 100000 callable(s) and generator(s), cost time: 1 s, clock time: 37 ms, avg: 379 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 159 ns +### Round: 2 ### +create 100000 callable(s) and generator(s), cost time: 1 s, clock time: 809 ms, avg: 8097 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 160 ns +### Round: 3 ### +create 100000 callable(s) and generator(s), cost time: 1 s, clock time: 807 ms, avg: 8079 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 157 ns +### Round: 4 ### +create 100000 callable(s) and generator(s), cost time: 1 s, clock time: 807 ms, avg: 8078 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 161 ns +### Round: 5 ### +create 100000 callable(s) and generator(s), cost time: 1 s, clock time: 800 ms, avg: 8003 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 156 ns +###################### std callable - reuse channel generator - trivial ################### +########## Cmd: bin/libcopp_sbsccrcg.exe +### Round: 1 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 34 ms, avg: 343 ns +remove 100000 callable(s), cost time: 0 s, clock time: 17 ms, avg: 178 ns +### Round: 2 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 48 ms, avg: 481 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 161 ns +### Round: 3 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 34 ms, avg: 346 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 158 ns +### Round: 4 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 34 ms, avg: 340 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 167 ns +### Round: 5 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 34 ms, avg: 349 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 168 ns +###################### std callable - reuse channel generator - no trivial ################### +########## Cmd: bin/libcopp_sbsccrcgnt.exe +### Round: 1 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 35 ms, avg: 350 ns +remove 100000 callable(s), cost time: 0 s, clock time: 17 ms, avg: 172 ns +### Round: 2 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 35 ms, avg: 353 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 166 ns +### Round: 3 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 34 ms, avg: 346 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 163 ns +### Round: 4 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 36 ms, avg: 360 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 163 ns +### Round: 5 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 41 ms, avg: 410 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 167 ns +###################### std callable - reuse generator - trivial ################### +########## Cmd: bin/libcopp_sbsccrg.exe +### Round: 1 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 41 ms, avg: 413 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 151 ns +### Round: 2 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 40 ms, avg: 404 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 159 ns +### Round: 3 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 40 ms, avg: 409 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 158 ns +### Round: 4 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 40 ms, avg: 402 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 157 ns +### Round: 5 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 41 ms, avg: 411 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 156 ns +###################### std callable - reuse generator - no trivial ################### +########## Cmd: bin/libcopp_sbsccrgnt.exe +### Round: 1 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 43 ms, avg: 437 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 161 ns +### Round: 2 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 40 ms, avg: 408 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 157 ns +### Round: 3 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 40 ms, avg: 402 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 152 ns +### Round: 4 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 49 ms, avg: 498 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 159 ns +### Round: 5 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 41 ms, avg: 413 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 161 ns +###################### std callable - reuse lightweight generator - trivial ################### +########## Cmd: bin/libcopp_sbsccrlg.exe +### Round: 1 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 38 ms, avg: 387 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 154 ns +### Round: 2 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 38 ms, avg: 380 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 161 ns +### Round: 3 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 37 ms, avg: 373 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 159 ns +### Round: 4 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 37 ms, avg: 378 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 157 ns +### Round: 5 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 37 ms, avg: 377 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 155 ns +###################### std callable - reuse lightweight generator - no trivial ################### +########## Cmd: bin/libcopp_sbsccrlgnt.exe +### Round: 1 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 38 ms, avg: 387 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 159 ns +### Round: 2 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 38 ms, avg: 387 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 161 ns +### Round: 3 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 38 ms, avg: 381 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 153 ns +### Round: 4 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 37 ms, avg: 378 ns +remove 100000 callable(s), cost time: 0 s, clock time: 15 ms, avg: 153 ns +### Round: 5 ### +create 100000 callable(s) and generator(s), cost time: 0 s, clock time: 38 ms, avg: 383 ns +remove 100000 callable(s), cost time: 0 s, clock time: 16 ms, avg: 168 ns +###################### std task - create generator - trivial ################### +########## Cmd: bin/libcopp_sbsctcg.exe +### Round: 1 ### +create 100000 task(s) and generator(s), cost time: 1 s, clock time: 127 ms, avg: 1272 ns +remove 100000 task(s), cost time: 0 s, clock time: 21 ms, avg: 213 ns +### Round: 2 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 126 ms, avg: 1269 ns +remove 100000 task(s), cost time: 0 s, clock time: 21 ms, avg: 213 ns +### Round: 3 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 131 ms, avg: 1313 ns +remove 100000 task(s), cost time: 0 s, clock time: 21 ms, avg: 212 ns +### Round: 4 ### +create 100000 task(s) and generator(s), cost time: 1 s, clock time: 132 ms, avg: 1326 ns +remove 100000 task(s), cost time: 0 s, clock time: 21 ms, avg: 213 ns +### Round: 5 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 130 ms, avg: 1309 ns +remove 100000 task(s), cost time: 0 s, clock time: 21 ms, avg: 216 ns +###################### std task - create generator - no trivial ################### +########## Cmd: bin/libcopp_sbsctcgnt.exe +### Round: 1 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 134 ms, avg: 1343 ns +remove 100000 task(s), cost time: 0 s, clock time: 24 ms, avg: 243 ns +### Round: 2 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 125 ms, avg: 1256 ns +remove 100000 task(s), cost time: 0 s, clock time: 23 ms, avg: 237 ns +### Round: 3 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 125 ms, avg: 1254 ns +remove 100000 task(s), cost time: 0 s, clock time: 24 ms, avg: 245 ns +### Round: 4 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 127 ms, avg: 1271 ns +remove 100000 task(s), cost time: 0 s, clock time: 24 ms, avg: 249 ns +### Round: 5 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 127 ms, avg: 1271 ns +remove 100000 task(s), cost time: 0 s, clock time: 25 ms, avg: 252 ns +###################### std task - reuse generator - trivial ################### +########## Cmd: bin/libcopp_sbsctrg.exe +### Round: 1 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 128 ms, avg: 1289 ns +remove 100000 task(s), cost time: 0 s, clock time: 21 ms, avg: 213 ns +### Round: 2 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 126 ms, avg: 1264 ns +remove 100000 task(s), cost time: 0 s, clock time: 25 ms, avg: 251 ns +### Round: 3 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 177 ms, avg: 1773 ns +remove 100000 task(s), cost time: 0 s, clock time: 21 ms, avg: 213 ns +### Round: 4 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 145 ms, avg: 1450 ns +remove 100000 task(s), cost time: 0 s, clock time: 26 ms, avg: 262 ns +### Round: 5 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 144 ms, avg: 1441 ns +remove 100000 task(s), cost time: 0 s, clock time: 21 ms, avg: 217 ns +###################### std task - reuse generator - no trivial ################### +########## Cmd: bin/libcopp_sbsctrgnt.exe +### Round: 1 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 132 ms, avg: 1324 ns +remove 100000 task(s), cost time: 0 s, clock time: 24 ms, avg: 248 ns +### Round: 2 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 126 ms, avg: 1268 ns +remove 100000 task(s), cost time: 0 s, clock time: 24 ms, avg: 248 ns +### Round: 3 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 130 ms, avg: 1303 ns +remove 100000 task(s), cost time: 0 s, clock time: 24 ms, avg: 243 ns +### Round: 4 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 125 ms, avg: 1255 ns +remove 100000 task(s), cost time: 0 s, clock time: 24 ms, avg: 248 ns +### Round: 5 ### +create 100000 task(s) and generator(s), cost time: 0 s, clock time: 136 ms, avg: 1366 ns +remove 100000 task(s), cost time: 0 s, clock time: 24 ms, avg: 245 ns +###################### context coroutine (stack using default allocator[VirtualAlloc]) ################### +########## Cmd: bin/libcopp_sbt.exe +create 100000 task, cost time: 1 s, clock time: 418 ms, avg: 4182 ns +switch 100000 tasks 10000000 times, cost time: 2 s, clock time: 2351 ms, avg: 235 ns +remove 100000 tasks, cost time: 0 s, clock time: 286 ms, avg: 2861 ns +###################### task (stack using malloc/free) ################### +########## Cmd: bin/libcopp_sbtm.exe +create 100000 task, cost time: 1 s, clock time: 556 ms, avg: 5560 ns +switch 100000 tasks 10000000 times, cost time: 4 s, clock time: 4213 ms, avg: 421 ns +remove 100000 tasks, cost time: 0 s, clock time: 146 ms, avg: 1461 ns +###################### task (stack using memory pool) ################### +########## Cmd: bin/libcopp_sbtmp.exe +create 100000 task, cost time: 0 s, clock time: 81 ms, avg: 816 ns +switch 100000 tasks 10000000 times, cost time: 2 s, clock time: 2339 ms, avg: 233 ns +remove 100000 tasks, cost time: 0 s, clock time: 15 ms, avg: 151 ns +###################### task (stack using stack pool) ################### +########## Cmd: bin/libcopp_sbtsp.exe +### Round: 1 ### +create 100000 task, cost time: 1 s, clock time: 466 ms, avg: 4669 ns +switch 100000 tasks 10000000 times, cost time: 2 s, clock time: 2513 ms, avg: 251 ns +remove 100000 tasks, cost time: 0 s, clock time: 15 ms, avg: 157 ns +### Round: 2 ### +create 100000 task, cost time: 0 s, clock time: 100 ms, avg: 1009 ns +switch 100000 tasks 10000000 times, cost time: 3 s, clock time: 2658 ms, avg: 265 ns +remove 100000 tasks, cost time: 0 s, clock time: 9 ms, avg: 99 ns +### Round: 3 ### +create 100000 task, cost time: 0 s, clock time: 82 ms, avg: 822 ns +switch 100000 tasks 10000000 times, cost time: 2 s, clock time: 2340 ms, avg: 234 ns +remove 100000 tasks, cost time: 0 s, clock time: 9 ms, avg: 96 ns +### Round: 4 ### +create 100000 task, cost time: 1 s, clock time: 81 ms, avg: 813 ns +switch 100000 tasks 10000000 times, cost time: 2 s, clock time: 2343 ms, avg: 234 ns +remove 100000 tasks, cost time: 0 s, clock time: 10 ms, avg: 108 ns +### Round: 5 ### +create 100000 task, cost time: 0 s, clock time: 80 ms, avg: 807 ns +switch 100000 tasks 10000000 times, cost time: 2 s, clock time: 2334 ms, avg: 233 ns +remove 100000 tasks, cost time: 0 s, clock time: 10 ms, avg: 102 ns diff --git a/docs/requirements-vscode.txt b/docs/requirements-vscode.txt index 4524bd0..57d789a 100644 --- a/docs/requirements-vscode.txt +++ b/docs/requirements-vscode.txt @@ -1,9 +1,9 @@ -pydocstyle>=4.0.1 +pydocstyle>=6.3.0 pep8>=1.7.1 -autopep8>=1.4.4 -yapf>=0.27.0 -pylint>=2.3.1 -flake8>=3.7.8 -doc8>=0.8.0 +autopep8>=2.3.2 +yapf>=0.43.0 +pylint>=4.0.8 +flake8>=7.3.0 +doc8>=2.0.0 # PATH for editor ${workspaceFolder}/py3env/bin/ \ No newline at end of file diff --git a/test/case/coroutine_context_channel_test.cpp b/test/case/coroutine_context_channel_test.cpp index 5cfc97b..3367293 100644 --- a/test/case/coroutine_context_channel_test.cpp +++ b/test/case/coroutine_context_channel_test.cpp @@ -543,3 +543,42 @@ CASE_TEST(coroutine_channel, multiple_callers_resume_fifo) { } } } + +CASE_TEST(coroutine_channel, multiple_callers_add_remove_edge_cases) { + int caller_indexes[3] = {0, 1, 2}; + copp::stackful_channel_handle_delegate first_caller; + copp::stackful_channel_handle_delegate second_caller; + copp::stackful_channel_handle_delegate unregistered_caller; + first_caller.handle_data = &caller_indexes[0]; + first_caller.resume_handle = &test_context_channel_fifo_resume; + second_caller.handle_data = &caller_indexes[1]; + second_caller.resume_handle = &test_context_channel_fifo_resume; + unregistered_caller.handle_data = &caller_indexes[2]; + unregistered_caller.resume_handle = &test_context_channel_fifo_resume; + + test_context_channel_fifo_context context; + + // Re-adding the same handle while it's the only caller keeps a single caller. + context.add_caller(first_caller); + context.add_caller(first_caller); + CASE_EXPECT_FALSE(context.has_multiple_callers()); + + // Removing a handle that was never registered returns false while single caller. + CASE_EXPECT_FALSE(context.remove_caller(second_caller)); + + // Convert to multiple callers, then a repeated registration is still ignored. + context.add_caller(second_caller); + context.add_caller(first_caller); + CASE_EXPECT_TRUE(context.has_multiple_callers()); + + // Removing a handle not present in multi-caller mode returns false. + CASE_EXPECT_FALSE(context.remove_caller(unregistered_caller)); + + // Removing the registered handles returns true and empties the caller set. + CASE_EXPECT_TRUE(context.remove_caller(first_caller)); + CASE_EXPECT_TRUE(context.remove_caller(second_caller)); + + g_test_coroutine_channel_fifo_order.clear(); + CASE_EXPECT_EQ(0, static_cast(context.resume_callers())); + CASE_EXPECT_TRUE(g_test_coroutine_channel_fifo_order.empty()); +} diff --git a/test/case/task_promise_test.cpp b/test/case/task_promise_test.cpp index 7466500..cfeedb6 100644 --- a/test/case/task_promise_test.cpp +++ b/test/case/task_promise_test.cpp @@ -414,8 +414,7 @@ static void generator_fifo_blocker_suspend_callback(generator_future_int_type::c static void generator_fifo_blocker_resume_callback(const generator_future_int_type::context_type &) {} static task_future_int_type task_func_fifo_blocker() { - generator_future_int_type generator{generator_fifo_blocker_suspend_callback, - generator_fifo_blocker_resume_callback}; + generator_future_int_type generator{generator_fifo_blocker_suspend_callback, generator_fifo_blocker_resume_callback}; auto res = co_await generator; co_return res; } @@ -460,6 +459,60 @@ CASE_TEST(task_promise, task_future_multiple_callers_resume_fifo) { } } +CASE_TEST(task_promise, task_future_caller_manager_dedup_and_remove) { + g_task_future_fifo_blocker_contexts.clear(); + g_task_future_fifo_resume_order.clear(); + + task_future_int_type blocker = task_func_fifo_blocker(); + CASE_EXPECT_TRUE(blocker.start()); + CASE_EXPECT_FALSE(blocker.is_exiting()); + + // Suspended waiters give us valid, non-done coroutine handles to drive the caller manager directly. + callable_future_int_type waiter0 = task_future_func_fifo_waiter(blocker, 0); + callable_future_int_type waiter1 = task_future_func_fifo_waiter(blocker, 1); + callable_future_int_type waiter2 = task_future_func_fifo_waiter(blocker, 2); + CASE_EXPECT_FALSE(waiter0.is_ready()); + CASE_EXPECT_FALSE(waiter1.is_ready()); + CASE_EXPECT_FALSE(waiter2.is_ready()); + + using caller_delegate = copp::promise_caller_manager::handle_delegate; + copp::promise_caller_manager manager; + CASE_EXPECT_FALSE(manager.has_multiple_callers()); + + // Re-adding the same handle while it's the only caller keeps a single caller. + manager.add_caller(caller_delegate{waiter0.get_internal_handle()}); + manager.add_caller(caller_delegate{waiter0.get_internal_handle()}); + CASE_EXPECT_FALSE(manager.has_multiple_callers()); + + // Removing a handle that was never registered returns false while single caller. + CASE_EXPECT_FALSE(manager.remove_caller(caller_delegate{waiter1.get_internal_handle()})); + + // Convert to multiple callers, then a repeated registration is still ignored. + manager.add_caller(caller_delegate{waiter1.get_internal_handle()}); + manager.add_caller(caller_delegate{waiter0.get_internal_handle()}); + manager.add_caller(caller_delegate{waiter1.get_internal_handle()}); + CASE_EXPECT_TRUE(manager.has_multiple_callers()); + + // Removing a handle not present in multi-caller mode returns false. + CASE_EXPECT_FALSE(manager.remove_caller(caller_delegate{waiter2.get_internal_handle()})); + + // Removing the registered handles returns true. + CASE_EXPECT_TRUE(manager.remove_caller(caller_delegate{waiter0.get_internal_handle()})); + CASE_EXPECT_TRUE(manager.remove_caller(caller_delegate{waiter1.get_internal_handle()})); + + // Complete the blocker so the real waiters unwind cleanly. + CASE_EXPECT_EQ(1, static_cast(g_task_future_fifo_blocker_contexts.size())); + if (!g_task_future_fifo_blocker_contexts.empty()) { + auto pending_context = g_task_future_fifo_blocker_contexts.front(); + g_task_future_fifo_blocker_contexts.pop_front(); + pending_context->set_value(0); + } + CASE_EXPECT_TRUE(blocker.is_exiting()); + CASE_EXPECT_TRUE(waiter0.is_ready()); + CASE_EXPECT_TRUE(waiter1.is_ready()); + CASE_EXPECT_TRUE(waiter2.is_ready()); +} + namespace { static callable_future_int_type task_func_await_callable_and_be_killed() { auto u = task_future_func_int_l2(13); From 5415988b5be0c13369d05c0ad2d8cf5e6ce66255 Mon Sep 17 00:00:00 2001 From: owent Date: Tue, 15 Sep 2026 18:36:54 +0800 Subject: [PATCH 5/5] Fixes channel wake up order. --- CHANGELOG.md | 3 +- src/libcopp/coroutine/stackful_channel.cpp | 3 +- .../coroutine/std_coroutine_common.cpp | 3 +- test/case/coroutine_context_channel_test.cpp | 41 ++++++++++++++++++ test/case/task_promise_test.cpp | 42 +++++++++++++++++++ 5 files changed, 89 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26ddca2..c06702a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ dual index of an order-preserving list and a hash map, so waiters queued behind the same task or channel wake in the order they registered, matching the legacy stackful `next_list` behavior, while dedup-on-add and passive removal stay O(1). Duplicate registrations of the same handle are now also ignored when - `LIBCOPP_MACRO_ENABLE_STD_VARIANT` is off. + `LIBCOPP_MACRO_ENABLE_STD_VARIANT` is off. FIFO order and deduplication are preserved when the first caller + is removed and callers are registered again. 2. Update dependencies. 3. Update benchmark results. diff --git a/src/libcopp/coroutine/stackful_channel.cpp b/src/libcopp/coroutine/stackful_channel.cpp index acc595b..451641b 100644 --- a/src/libcopp/coroutine/stackful_channel.cpp +++ b/src/libcopp/coroutine/stackful_channel.cpp @@ -64,7 +64,8 @@ LIBCOPP_COPP_API void stackful_channel_context_base::add_caller(handle_delegate callers.add(handle); callers_.emplace(std::move(callers)); #else - if (!unique_caller_) { + // The single-caller slot is resumed first, so only reuse it when no callers are queued. + if (!unique_caller_ && (!multiple_callers_ || multiple_callers_->size() == 0)) { unique_caller_ = handle; return; } diff --git a/src/libcopp/coroutine/std_coroutine_common.cpp b/src/libcopp/coroutine/std_coroutine_common.cpp index 8a9a0b3..48875a3 100644 --- a/src/libcopp/coroutine/std_coroutine_common.cpp +++ b/src/libcopp/coroutine/std_coroutine_common.cpp @@ -55,7 +55,8 @@ LIBCOPP_COPP_API void promise_caller_manager::add_caller(handle_delegate delegat callers.add(delegate); callers_.emplace(std::move(callers)); # else - if (!unique_caller_.handle) { + // The single-caller slot is resumed first, so only reuse it when no callers are queued. + if (!unique_caller_.handle && (!multiple_callers_ || multiple_callers_->size() == 0)) { unique_caller_ = delegate; return; } diff --git a/test/case/coroutine_context_channel_test.cpp b/test/case/coroutine_context_channel_test.cpp index 3367293..394390e 100644 --- a/test/case/coroutine_context_channel_test.cpp +++ b/test/case/coroutine_context_channel_test.cpp @@ -544,6 +544,38 @@ CASE_TEST(coroutine_channel, multiple_callers_resume_fifo) { } } +CASE_TEST(coroutine_channel, multiple_callers_resume_fifo_after_first_removed) { + int caller_indexes[3] = {0, 1, 2}; + copp::stackful_channel_handle_delegate callers[3]; + test_context_channel_fifo_context context; + for (int index = 0; index < 3; ++index) { + callers[index].handle_data = &caller_indexes[index]; + callers[index].resume_handle = &test_context_channel_fifo_resume; + } + + context.add_caller(callers[0]); + context.add_caller(callers[1]); + CASE_EXPECT_TRUE(context.remove_caller(callers[0])); + CASE_EXPECT_FALSE(context.has_multiple_callers()); + + // New and re-registered callers must stay behind the remaining waiter. + context.add_caller(callers[2]); + context.add_caller(callers[0]); + context.add_caller(callers[1]); + CASE_EXPECT_TRUE(context.has_multiple_callers()); + + g_test_coroutine_channel_fifo_order.clear(); + CASE_EXPECT_EQ(3, static_cast(context.resume_callers())); + CASE_EXPECT_EQ(3, static_cast(g_test_coroutine_channel_fifo_order.size())); + if (g_test_coroutine_channel_fifo_order.size() == 3) { + CASE_EXPECT_EQ(1, g_test_coroutine_channel_fifo_order[0]); + CASE_EXPECT_EQ(2, g_test_coroutine_channel_fifo_order[1]); + CASE_EXPECT_EQ(0, g_test_coroutine_channel_fifo_order[2]); + } + CASE_EXPECT_FALSE(context.has_multiple_callers()); + CASE_EXPECT_EQ(0, static_cast(context.resume_callers())); +} + CASE_TEST(coroutine_channel, multiple_callers_add_remove_edge_cases) { int caller_indexes[3] = {0, 1, 2}; copp::stackful_channel_handle_delegate first_caller; @@ -576,9 +608,18 @@ CASE_TEST(coroutine_channel, multiple_callers_add_remove_edge_cases) { // Removing the registered handles returns true and empties the caller set. CASE_EXPECT_TRUE(context.remove_caller(first_caller)); + // Re-adding the remaining caller must not duplicate it into the vacant single-caller slot. + context.add_caller(second_caller); + CASE_EXPECT_FALSE(context.has_multiple_callers()); CASE_EXPECT_TRUE(context.remove_caller(second_caller)); + CASE_EXPECT_FALSE(context.remove_caller(second_caller)); g_test_coroutine_channel_fifo_order.clear(); CASE_EXPECT_EQ(0, static_cast(context.resume_callers())); CASE_EXPECT_TRUE(g_test_coroutine_channel_fifo_order.empty()); + + context.add_caller(first_caller); + CASE_EXPECT_FALSE(context.has_multiple_callers()); + CASE_EXPECT_EQ(1, static_cast(context.resume_callers())); + CASE_EXPECT_EQ(1, static_cast(g_test_coroutine_channel_fifo_order.size())); } diff --git a/test/case/task_promise_test.cpp b/test/case/task_promise_test.cpp index cfeedb6..9aab646 100644 --- a/test/case/task_promise_test.cpp +++ b/test/case/task_promise_test.cpp @@ -459,6 +459,43 @@ CASE_TEST(task_promise, task_future_multiple_callers_resume_fifo) { } } +CASE_TEST(task_promise, task_future_multiple_callers_resume_fifo_after_first_killed) { + g_task_future_fifo_blocker_contexts.clear(); + g_task_future_fifo_resume_order.clear(); + + task_future_int_type blocker = task_func_fifo_blocker(); + CASE_EXPECT_TRUE(blocker.start()); + callable_future_int_type waiter0 = task_future_func_fifo_waiter(blocker, 0); + callable_future_int_type waiter1 = task_future_func_fifo_waiter(blocker, 1); + CASE_EXPECT_FALSE(waiter0.is_ready()); + CASE_EXPECT_FALSE(waiter1.is_ready()); + + // Killing the first waiter detaches it while the second waiter remains queued. + CASE_EXPECT_TRUE(waiter0.kill()); + CASE_EXPECT_TRUE(waiter0.is_ready()); + CASE_EXPECT_FALSE(blocker.is_exiting()); + CASE_EXPECT_FALSE(waiter1.is_ready()); + CASE_EXPECT_TRUE(g_task_future_fifo_resume_order.empty()); + + callable_future_int_type waiter2 = task_future_func_fifo_waiter(blocker, 2); + CASE_EXPECT_FALSE(waiter2.is_ready()); + CASE_EXPECT_EQ(1, static_cast(g_task_future_fifo_blocker_contexts.size())); + if (!g_task_future_fifo_blocker_contexts.empty()) { + auto pending_context = g_task_future_fifo_blocker_contexts.front(); + g_task_future_fifo_blocker_contexts.pop_front(); + pending_context->set_value(0); + } + + CASE_EXPECT_TRUE(blocker.is_exiting()); + CASE_EXPECT_TRUE(waiter1.is_ready()); + CASE_EXPECT_TRUE(waiter2.is_ready()); + CASE_EXPECT_EQ(2, static_cast(g_task_future_fifo_resume_order.size())); + if (g_task_future_fifo_resume_order.size() == 2) { + CASE_EXPECT_EQ(1, g_task_future_fifo_resume_order[0]); + CASE_EXPECT_EQ(2, g_task_future_fifo_resume_order[1]); + } +} + CASE_TEST(task_promise, task_future_caller_manager_dedup_and_remove) { g_task_future_fifo_blocker_contexts.clear(); g_task_future_fifo_resume_order.clear(); @@ -498,7 +535,12 @@ CASE_TEST(task_promise, task_future_caller_manager_dedup_and_remove) { // Removing the registered handles returns true. CASE_EXPECT_TRUE(manager.remove_caller(caller_delegate{waiter0.get_internal_handle()})); + // Re-adding the remaining caller must not duplicate it into the vacant single-caller slot. + manager.add_caller(caller_delegate{waiter1.get_internal_handle()}); + CASE_EXPECT_FALSE(manager.has_multiple_callers()); CASE_EXPECT_TRUE(manager.remove_caller(caller_delegate{waiter1.get_internal_handle()})); + CASE_EXPECT_FALSE(manager.remove_caller(caller_delegate{waiter1.get_internal_handle()})); + CASE_EXPECT_EQ(0, static_cast(manager.resume_callers())); // Complete the blocker so the real waiters unwind cleanly. CASE_EXPECT_EQ(1, static_cast(g_task_future_fifo_blocker_contexts.size()));