benchmarks/PureSwitch.bench.cpp (80 lines of code) (raw):

/* * Copyright (c) 2022, Alibaba Group Holding Limited; * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "PureSwitch.bench.h" #include "async_simple/executors/SimpleExecutor.h" #include "async_simple/experimental/coroutine.h" #ifdef ASYNC_SIMPLE_BENCHMARK_UTHREAD #define private public #include "async_simple/uthread/Uthread.h" #undef private #include "async_simple/uthread/Async.h" #endif using namespace async_simple; using namespace async_simple::executors; #ifdef ASYNC_SIMPLE_BENCHMARK_UTHREAD using namespace async_simple::uthread; #endif template <typename T> struct Generator { struct promise_type; using Handle = std::coroutine_handle<promise_type>; Generator(Handle h) : handle_(h) {} ~Generator() { handle_.destroy(); } struct promise_type { T val_; auto get_return_object() { return Handle::from_promise(*this); } auto initial_suspend() { return std::suspend_always{}; } auto final_suspend() noexcept { return std::suspend_always{}; } auto yield_value(T val) { this->val_ = val; return std::suspend_always{}; } void unhandled_exception() {} void return_value(T val) { this->val_ = val; } }; T operator()() { handle_.resume(); return handle_.promise().val_; } private: Handle handle_; }; Generator<int> f() { [[maybe_unused]] int i = 0; while (true) { co_yield i; i++; } } void Generator_pure_switch_bench(benchmark::State &state) { int num = state.range(0); SimpleExecutor e(1); for (auto _ : state) { auto g = f(); for (int i = 0; i < num; ++i) { int value = g(); benchmark::DoNotOptimize(value); } } } #ifdef ASYNC_SIMPLE_BENCHMARK_UTHREAD void Uthread_pure_switch_bench(benchmark::State &state) { int num = state.range(0); SimpleExecutor e(1); for (auto _ : state) { async<Launch::Current>( [&e, num]() { auto t1 = async<Launch::Prompt>( []() { auto ctx = uthread::internal::thread_impl::get(); while (true) { uthread::internal::thread_impl::switch_out(ctx); } }, &e); for (int i = 0; i < num; ++i) { t1._ctx->switch_in(); } }, &e); } } #endif