} | } | ||||
} | } | ||||
#if _HAS_CXX17 | |||||
future_vt RunPingPongEchoClient(asio::io_service & ios, tcp::resolver::iterator ep) | future_vt RunPingPongEchoClient(asio::io_service & ios, tcp::resolver::iterator ep) | ||||
{ | { | ||||
tcp::socket socket_{ ios }; | tcp::socket socket_{ ios }; | ||||
std::cout << e.what() << std::endl; | std::cout << e.what() << std::endl; | ||||
} | } | ||||
} | } | ||||
#endif | |||||
class chat_session : public std::enable_shared_from_this<chat_session> | class chat_session : public std::enable_shared_from_this<chat_session> | ||||
{ | { |
#include "src/channel.h" | #include "src/channel.h" | ||||
#include "src/scheduler.h" | #include "src/scheduler.h" | ||||
#include "src/sleep.h" | #include "src/sleep.h" | ||||
#if _HAS_CXX17 | |||||
#include "src/when.h" | #include "src/when.h" | ||||
#endif |
RF_API future_t<bool> try_lock_until_(const clock_type::time_point & tp) const; | RF_API future_t<bool> try_lock_until_(const clock_type::time_point & tp) const; | ||||
}; | }; | ||||
#if _HAS_CXX17 | |||||
#define resumf_guard_lock(lker) (lker).lock(); resumef::scoped_lock<resumef::mutex_t> __resumf_guard##lker##__(std::adopt_lock, (lker)) | #define resumf_guard_lock(lker) (lker).lock(); resumef::scoped_lock<resumef::mutex_t> __resumf_guard##lker##__(std::adopt_lock, (lker)) | ||||
#else | |||||
#define resumf_guard_lock(lker) (lker).lock(); resumef::scoped_lock<resumef::mutex_t> __resumf_guard##lker##__((lker), std::adopt_lock) | |||||
#endif | |||||
} | } |
#include "when.h" | |||||
#include "_awaker.h" | |||||
#if _HAS_CXX17 | |||||
#include "when.h" | |||||
#include <assert.h> | #include <assert.h> | ||||
namespace resumef | namespace resumef | ||||
} | } | ||||
} | } | ||||
} | } | ||||
#endif |
#include "librf.h" | #include "librf.h" | ||||
static const int N = 10000000; | |||||
static const intptr_t N = 10000000; | |||||
//static const int N = 10; | //static const int N = 10; | ||||
static std::mutex lock_console; | |||||
template <typename T> | template <typename T> | ||||
void dump(std::string name, int n, T start, T end) | |||||
void dump(size_t idx, std::string name, T start, T end) | |||||
{ | { | ||||
lock_console.lock(); | |||||
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count(); | auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count(); | ||||
std::cout << name << " " << n << " " << ns << " ns " << ns / n << " ns/op" << std::endl; | |||||
std::cout << idx << ":" << name << " "; | |||||
std::cout << N << " " << ns << " ns "; | |||||
std::cout << (ns / N) << " ns/op" << " "; | |||||
std::cout << (N * 100 * 1000 / ns) << "w/cps" << std::endl; | |||||
lock_console.unlock(); | |||||
} | } | ||||
auto yield_switch(int coro) | |||||
auto yield_switch(intptr_t coro) | |||||
{ | { | ||||
for (int i = 0; i < N / coro; ++i) | |||||
for (intptr_t i = 0; i < N / coro; ++i) | |||||
co_yield i; | co_yield i; | ||||
return N / coro; | return N / coro; | ||||
} | } | ||||
void resumable_switch(int coro) | |||||
void resumable_switch(intptr_t coro, size_t idx) | |||||
{ | { | ||||
resumef::local_scheduler ls; | |||||
auto start = std::chrono::steady_clock::now(); | auto start = std::chrono::steady_clock::now(); | ||||
for (int i = 0; i < coro; ++i) | |||||
for (intptr_t i = 0; i < coro; ++i) | |||||
{ | { | ||||
//go yield_switch(coro); | //go yield_switch(coro); | ||||
go [=] | go [=] | ||||
{ | { | ||||
for (int i = 0; i < N / coro; ++i) | |||||
for (intptr_t i = 0; i < N / coro; ++i) | |||||
co_yield i; | co_yield i; | ||||
return N / coro; | return N / coro; | ||||
}; | }; | ||||
resumef::this_scheduler()->run_until_notask(); | resumef::this_scheduler()->run_until_notask(); | ||||
auto end = std::chrono::steady_clock::now(); | auto end = std::chrono::steady_clock::now(); | ||||
dump("BenchmarkSwitch_" + std::to_string(coro), N, start, end); | |||||
dump(idx, "BenchmarkSwitch_" + std::to_string(coro), start, end); | |||||
} | } | ||||
void resumable_main_resumable() | void resumable_main_resumable() | ||||
{ | { | ||||
resumable_switch(1); | |||||
resumable_switch(10); | |||||
resumable_switch(100); | |||||
resumable_switch(1000); | |||||
resumable_switch(10000); | |||||
//resumable_switch(1, 0); | |||||
//resumable_switch(10, 0); | |||||
//resumable_switch(100, 0); | |||||
//resumable_switch(10000, 0); | |||||
//resumable_switch(10000000, 0); | |||||
//resumable_switch(10000000); | |||||
std::thread works[32]; | |||||
for (size_t w = 1; w <= _countof(works); ++w) | |||||
{ | |||||
for (size_t idx = 0; idx < w; ++idx) | |||||
works[idx] = std::thread(&resumable_switch, 1000, idx); | |||||
for (size_t idx = 0; idx < w; ++idx) | |||||
works[idx].join(); | |||||
std::cout << std::endl << std::endl; | |||||
} | |||||
} | } |
#include "librf.h" | #include "librf.h" | ||||
#if _HAS_CXX17 | |||||
using namespace resumef; | using namespace resumef; | ||||
void test_when_any() | void test_when_any() | ||||
}; | }; | ||||
this_scheduler()->run_until_notask(); | this_scheduler()->run_until_notask(); | ||||
} | } | ||||
#endif | |||||
void resumable_main_when_all() | void resumable_main_when_all() | ||||
{ | { | ||||
#if _HAS_CXX17 | |||||
srand((uint32_t)time(nullptr)); | srand((uint32_t)time(nullptr)); | ||||
test_when_any(); | test_when_any(); | ||||
std::cout << std::endl; | std::cout << std::endl; | ||||
test_when_all(); | test_when_all(); | ||||
#endif | |||||
} | } | ||||
int main(int argc, const char * argv[]) | int main(int argc, const char * argv[]) | ||||
{ | { | ||||
if (argc > 1) | |||||
resumable_main_benchmark_asio_client(atoi(argv[1])); | |||||
else | |||||
resumable_main_benchmark_asio_server(); | |||||
resumable_main_resumable(); | |||||
//if (argc > 1) | |||||
// resumable_main_benchmark_asio_client(atoi(argv[1])); | |||||
//else | |||||
// resumable_main_benchmark_asio_server(); | |||||
return 0; | return 0; | ||||
//resumable_main_resumable(); | |||||
resumable_main_when_all(); | resumable_main_when_all(); | ||||
resumable_main_multi_thread(); | resumable_main_multi_thread(); |
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> | ||||
<ConfigurationType>Application</ConfigurationType> | <ConfigurationType>Application</ConfigurationType> | ||||
<UseDebugLibraries>true</UseDebugLibraries> | <UseDebugLibraries>true</UseDebugLibraries> | ||||
<PlatformToolset>v141</PlatformToolset> | |||||
<PlatformToolset>v140</PlatformToolset> | |||||
<CharacterSet>NotSet</CharacterSet> | <CharacterSet>NotSet</CharacterSet> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> | ||||
<Optimization>MaxSpeed</Optimization> | <Optimization>MaxSpeed</Optimization> | ||||
<FunctionLevelLinking>true</FunctionLevelLinking> | <FunctionLevelLinking>true</FunctionLevelLinking> | ||||
<IntrinsicFunctions>true</IntrinsicFunctions> | <IntrinsicFunctions>true</IntrinsicFunctions> | ||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;ASIO_STANDALONE;RESUMEF_ENABLE_MULT_SCHEDULER=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;ASIO_STANDALONE;RESUMEF_ENABLE_MULT_SCHEDULER=1;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||||
<AdditionalIncludeDirectories>..\librf;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | <AdditionalIncludeDirectories>..\librf;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||||
<AdditionalOptions>/await</AdditionalOptions> | <AdditionalOptions>/await</AdditionalOptions> | ||||
<ExceptionHandling>Sync</ExceptionHandling> | <ExceptionHandling>Sync</ExceptionHandling> |