benchmarks/Uthread.bench.cpp (140 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 "Uthread.bench.h"
#include <thread>
#include <vector>
#include "async_simple/executors/SimpleExecutor.h"
using namespace std;
using namespace async_simple;
using namespace async_simple::uthread;
template <class Func>
void delayedTask(Executor* ex, Func&& func, std::size_t ms) {
std::thread(
[f = std::move(func), ms](Executor* ex) {
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
ex->schedule(std::move(f));
},
ex)
.detach();
}
void Uthread_switch(benchmark::State& state) {
async_simple::executors::SimpleExecutor executor(10);
auto test = [&]() {
auto Job = [&]() -> Future<int> {
Promise<int> p;
auto f = p.getFuture().via(&executor);
delayedTask(
&executor,
[p = std::move(p)]() mutable {
auto value = 1024;
p.setValue(value);
},
100);
return f;
};
constexpr size_t n = 10;
std::atomic<int> running = n;
auto UthreadTask = [&executor, &running, &Job]() {
Uthread task(Attribute{&executor}, [&running, &Job]() {
await(Job());
running--;
});
task.detach();
};
for (size_t i = 0; i < n; i++)
executor.schedule(UthreadTask);
while (running) {
}
};
for ([[maybe_unused]] const auto& _ : state)
test();
}
void Uthread_async(benchmark::State& state) {
async_simple::executors::SimpleExecutor executor(10);
auto test = [&]() {
auto Job = [&]() -> Future<int> {
Promise<int> p;
auto f = p.getFuture().via(&executor);
delayedTask(
&executor,
[p = std::move(p)]() mutable {
auto value = 1024;
p.setValue(value);
},
100);
return f;
};
constexpr size_t n = 10;
std::atomic<int> running = n;
for (size_t i = 0; i < n; i++)
async<Launch::Schedule>(
[&running, &Job]() {
await(Job());
running--;
},
&executor);
while (running) {
}
};
for ([[maybe_unused]] const auto& _ : state)
test();
}
void Uthread_await(benchmark::State& state) {
async_simple::executors::SimpleExecutor executor(10);
auto test = [&]() {
auto Job = [&](Promise<int> p) {
delayedTask(
&executor,
[p = std::move(p)]() mutable {
auto value = 1024;
p.setValue(value);
},
100);
};
constexpr size_t n = 10;
std::atomic<int> running = n;
for (size_t i = 0; i < n; i++)
async<Launch::Schedule>(
[&executor, &running, &Job]() {
await<int>(&executor, Job);
running--;
},
&executor);
while (running) {
}
};
for ([[maybe_unused]] const auto& _ : state)
test();
}
void Uthread_collectAll(benchmark::State& state) {
async_simple::executors::SimpleExecutor executor(10);
auto test = [&]() {
auto Job = [&](std::size_t delay_ms) -> Future<int> {
Promise<int> p;
auto f = p.getFuture().via(&executor);
delayedTask(
&executor,
[p = std::move(p)]() mutable {
auto value = 1024;
p.setValue(value);
},
delay_ms);
return f;
};
constexpr size_t n = 10;
std::vector<std::function<std::size_t()>> Tasks;
for (size_t i = 0; i < n; ++i)
Tasks.emplace_back(
[i, &Job]() -> std::size_t { return i + await(Job(n - i)); });
std::atomic<bool> running = true;
async<Launch::Schedule>(
[&running, &executor, Tasks = std::move(Tasks)]() mutable {
collectAll<Launch::Schedule>(Tasks.begin(), Tasks.end(),
&executor);
running = false;
},
&executor);
while (running) {
}
};
for ([[maybe_unused]] const auto& _ : state)
test();
}