feat add fiber switch benchmark
All checks were successful
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (Debug) (push) Successful in 1m40s
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (Release) (push) Successful in 2m34s
linux-arm-gcc / linux-gcc-arm (Debug) (push) Successful in 1m38s
linux-arm-gcc / linux-gcc-arm (Release) (push) Successful in 1m37s
linux-arm-gcc / linux-gcc-armhf (Debug) (push) Successful in 2m10s
linux-arm-gcc / linux-gcc-armhf (Release) (push) Successful in 1m44s
linux-mips-gcc / linux-gcc-mipsel (Debug) (push) Successful in 1m26s
linux-mips-gcc / linux-gcc-mipsel (Release) (push) Successful in 1m33s
linux-mips64-gcc / linux-gcc-mips64el (Debug) (push) Successful in 1m24s
linux-mips64-gcc / linux-gcc-mips64el (Release) (push) Successful in 3m57s
linux-riscv64-gcc / linux-gcc-riscv64 (Debug) (push) Successful in 3m6s
linux-riscv64-gcc / linux-gcc-riscv64 (Release) (push) Successful in 1m44s
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 2m2s
linux-x64-gcc / linux-gcc (Release) (push) Successful in 2m4s
linux-x86-gcc / linux-gcc (Debug) (push) Successful in 2m15s
linux-x86-gcc / linux-gcc (Release) (push) Successful in 2m37s
All checks were successful
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (Debug) (push) Successful in 1m40s
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (Release) (push) Successful in 2m34s
linux-arm-gcc / linux-gcc-arm (Debug) (push) Successful in 1m38s
linux-arm-gcc / linux-gcc-arm (Release) (push) Successful in 1m37s
linux-arm-gcc / linux-gcc-armhf (Debug) (push) Successful in 2m10s
linux-arm-gcc / linux-gcc-armhf (Release) (push) Successful in 1m44s
linux-mips-gcc / linux-gcc-mipsel (Debug) (push) Successful in 1m26s
linux-mips-gcc / linux-gcc-mipsel (Release) (push) Successful in 1m33s
linux-mips64-gcc / linux-gcc-mips64el (Debug) (push) Successful in 1m24s
linux-mips64-gcc / linux-gcc-mips64el (Release) (push) Successful in 3m57s
linux-riscv64-gcc / linux-gcc-riscv64 (Debug) (push) Successful in 3m6s
linux-riscv64-gcc / linux-gcc-riscv64 (Release) (push) Successful in 1m44s
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 2m2s
linux-x64-gcc / linux-gcc (Release) (push) Successful in 2m4s
linux-x86-gcc / linux-gcc (Debug) (push) Successful in 2m15s
linux-x86-gcc / linux-gcc (Release) (push) Successful in 2m37s
This commit is contained in:
parent
4fc64d5028
commit
31ca7c9f6b
@ -21,6 +21,9 @@ option(TILE_WITH_OPENSSL "Build with openssl" OFF)
|
|||||||
option(TILE_BUILD_SHARED "Build shared library" ON)
|
option(TILE_BUILD_SHARED "Build shared library" ON)
|
||||||
option(TILE_BUILD_STATIC "Build static library" ON)
|
option(TILE_BUILD_STATIC "Build static library" ON)
|
||||||
|
|
||||||
|
# set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "time")
|
||||||
|
# set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "time")
|
||||||
|
|
||||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||||
set(TILE_BUILD_TESTS ON)
|
set(TILE_BUILD_TESTS ON)
|
||||||
set(TILE_BUILD_BENCHMARKS ON)
|
set(TILE_BUILD_BENCHMARKS ON)
|
||||||
@ -207,6 +210,9 @@ endif()
|
|||||||
|
|
||||||
add_library(tile OBJECT ${TILE_SRCS})
|
add_library(tile OBJECT ${TILE_SRCS})
|
||||||
set_target_properties(tile PROPERTIES VERSION ${PROJECT_VERSION}
|
set_target_properties(tile PROPERTIES VERSION ${PROJECT_VERSION}
|
||||||
|
target_precompile_headers(tile PUBLIC inja/inja.h)
|
||||||
|
target_precompile_headers(tile PUBLIC inja/string_view.h)
|
||||||
|
target_precompile_headers(tile PUBLIC json/nlohann/json.hpp)
|
||||||
SOVERSION "${tile_VERSION_MAJRO}")
|
SOVERSION "${tile_VERSION_MAJRO}")
|
||||||
# target_sources(tile PRIVATE ${TILE_SRCS})
|
# target_sources(tile PRIVATE ${TILE_SRCS})
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
@ -358,6 +364,7 @@ if(TILE_BUILD_BENCHMARKS)
|
|||||||
target_sources(tile_bm_all PRIVATE ${benchmark_file})
|
target_sources(tile_bm_all PRIVATE ${benchmark_file})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
tile_add_bm(fiber_detail_fiber_benchmark "tile/fiber/detail/fiber_benchmark.cc")
|
||||||
tile_add_bm(base_casting_benchmark "tile/base/casting_benchmark.cc")
|
tile_add_bm(base_casting_benchmark "tile/base/casting_benchmark.cc")
|
||||||
tile_add_bm(base_thread_mutex_benchmark "tile/base/thread/mutex_benchmark.cc")
|
tile_add_bm(base_thread_mutex_benchmark "tile/base/thread/mutex_benchmark.cc")
|
||||||
tile_add_bm(base_encoding_benchmark "tile/base/encoding_benchmark.cc")
|
tile_add_bm(base_encoding_benchmark "tile/base/encoding_benchmark.cc")
|
||||||
|
45
tile/fiber/detail/fiber_benchmark.cc
Normal file
45
tile/fiber/detail/fiber_benchmark.cc
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include "tile/base/random.h"
|
||||||
|
#include "tile/fiber/detail/fiber.h"
|
||||||
|
|
||||||
|
#include "benchmark/benchmark.h"
|
||||||
|
namespace tile {
|
||||||
|
namespace fiber {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
void Benchmark_FiberSwitch(benchmark::State &state) {
|
||||||
|
constexpr int kFiberCount = 10000;
|
||||||
|
std::unique_ptr<Fiber> master;
|
||||||
|
std::unique_ptr<Fiber> worker[kFiberCount];
|
||||||
|
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
|
master = Fiber::Create([&]() {
|
||||||
|
while (state.KeepRunning()) {
|
||||||
|
++cnt;
|
||||||
|
worker[Random(kFiberCount - 1)]->Resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt = -1;
|
||||||
|
for (int i = 0; i != kFiberCount; ++i) {
|
||||||
|
worker[i]->Resume();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int i = 0; i != kFiberCount; ++i) {
|
||||||
|
worker[i] = Fiber::Create([&, i]() {
|
||||||
|
while (cnt != -1) {
|
||||||
|
master->Resume();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SetUpMasterFiber(master.get());
|
||||||
|
SetUpCurrentFiber(nullptr);
|
||||||
|
|
||||||
|
master->Resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(Benchmark_FiberSwitch);
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace fiber
|
||||||
|
} // namespace tile
|
@ -20,9 +20,25 @@ void Scheduler::SwitchTo(Fiber *self, Fiber *to) {
|
|||||||
void Scheduler::Yield(Fiber *self) {
|
void Scheduler::Yield(Fiber *self) {
|
||||||
auto master = GetMasterFiber();
|
auto master = GetMasterFiber();
|
||||||
|
|
||||||
|
TILE_CHECK(self, "self fiber is nullptr.");
|
||||||
|
TILE_CHECK(master, "Master fiber is not set.");
|
||||||
master->state_ = FiberState::Runnable;
|
master->state_ = FiberState::Runnable;
|
||||||
|
self->state_ = FiberState::Running;
|
||||||
SwitchTo(self, master);
|
SwitchTo(self, master);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scheduler::Halt(Fiber *self) {
|
||||||
|
TILE_CHECK_EQ(self, GetCurrentFiber(), "Fiber is not current fiber.");
|
||||||
|
TILE_CHECK(self->state() == FiberState::Running, "Fiber is not running.");
|
||||||
|
|
||||||
|
auto master = GetMasterFiber();
|
||||||
|
self->state_ = FiberState::Waiting;
|
||||||
|
|
||||||
|
master->Resume();
|
||||||
|
|
||||||
|
TILE_CHECK_EQ(self, GetCurrentFiber());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace fiber
|
} // namespace fiber
|
||||||
} // namespace tile
|
} // namespace tile
|
||||||
|
@ -15,6 +15,7 @@ public:
|
|||||||
|
|
||||||
void SwitchTo(Fiber *self, Fiber *to);
|
void SwitchTo(Fiber *self, Fiber *to);
|
||||||
void Yield(Fiber *self);
|
void Yield(Fiber *self);
|
||||||
|
void Halt(Fiber *self);
|
||||||
};
|
};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace fiber
|
} // namespace fiber
|
||||||
|
@ -11,7 +11,7 @@ namespace detail {
|
|||||||
|
|
||||||
TEST(Fiber, Resume) {
|
TEST(Fiber, Resume) {
|
||||||
constexpr int kFiberCount = 1000;
|
constexpr int kFiberCount = 1000;
|
||||||
constexpr int kSwitchCount = 100000;
|
constexpr int kSwitchCount = 1000 * 1000;
|
||||||
|
|
||||||
std::unique_ptr<Fiber> master;
|
std::unique_ptr<Fiber> master;
|
||||||
std::unique_ptr<Fiber> worker[kFiberCount];
|
std::unique_ptr<Fiber> worker[kFiberCount];
|
||||||
|
42
tile/fiber/detail/waitable.cc
Normal file
42
tile/fiber/detail/waitable.cc
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "tile/fiber/detail/waitable.h"
|
||||||
|
#include "tile/base/thread/scoped_lock.h"
|
||||||
|
|
||||||
|
namespace tile {
|
||||||
|
namespace fiber {
|
||||||
|
namespace detail {
|
||||||
|
WaitList::WaitList() {}
|
||||||
|
WaitList::~WaitList() {}
|
||||||
|
|
||||||
|
bool WaitList::AddWaiter(WaitListNode *node) {
|
||||||
|
ScopedLock _(lock_);
|
||||||
|
TILE_CHECK(node->waiter);
|
||||||
|
|
||||||
|
waiters_.push_back(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Fiber *WaitList::WakeOne() {
|
||||||
|
ScopedLock _(lock_);
|
||||||
|
while (true) {
|
||||||
|
if (waiters_.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
WaitListNode *waiter = waiters_.front();
|
||||||
|
waiters_.pop_front();
|
||||||
|
if (!waiter) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waiter->satisfied.exchange(true, std::memory_order_relaxed)) {
|
||||||
|
continue;
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return waiter->waiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace fiber
|
||||||
|
} // namespace tile
|
48
tile/fiber/detail/waitable.h
Normal file
48
tile/fiber/detail/waitable.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#ifndef TILE_FIBER_DETAIL_WAITABLE_H
|
||||||
|
#define TILE_FIBER_DETAIL_WAITABLE_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "tile/base/internal/singly_linked_list.h"
|
||||||
|
#include "tile/base/thread/spinlock.h"
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
namespace tile {
|
||||||
|
namespace fiber {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class Fiber;
|
||||||
|
class Scheduler;
|
||||||
|
|
||||||
|
struct WaitListNode {
|
||||||
|
Fiber *waiter = nullptr;
|
||||||
|
tile::internal::SinglyLinkedListEntry chain;
|
||||||
|
std::atomic<bool> satisfied{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
class WaitList {
|
||||||
|
public:
|
||||||
|
WaitList();
|
||||||
|
~WaitList();
|
||||||
|
|
||||||
|
bool AddWaiter(WaitListNode *node);
|
||||||
|
// Remove the waiter from the list.
|
||||||
|
// return true if the waiter is removed, otherwise return nullptr.
|
||||||
|
Fiber *WakeOne();
|
||||||
|
|
||||||
|
WaitList(const WaitList &) = delete;
|
||||||
|
WaitList &operator=(const WaitList &) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Spinlock lock_;
|
||||||
|
std::list<WaitListNode *> waiters_;
|
||||||
|
// tile::internal::SinglyLinkedList<WaitListNode, &WaitListNode::chain>
|
||||||
|
// waiters_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace fiber
|
||||||
|
} // namespace tile
|
||||||
|
|
||||||
|
#endif // TILE_FIBER_DETAIL_WAITABLE_H
|
Loading…
Reference in New Issue
Block a user