Browse Source

添加一个基于ASIO的pingpong性能评测

tags/v2.9.7
tearshark 5 years ago
parent
commit
7ed4d830b3

+ 227
- 0
benchmark/benchmark_asio_echo.cpp View File

@@ -0,0 +1,227 @@
#include <SDKDDKVer.h>
/*
#include <chrono>
#include <iostream>
#include <string>
#include <conio.h>
#include <thread>
*/
#include <asio.hpp>
#include "librf.h"
#include "src/asio_task.h"
#pragma warning(disable : 4834)
using namespace asio;
using namespace asio::ip;
using namespace resumef;
template<class _Ty, size_t _Size>
union uarray
{
std::array<_Ty, _Size> c;
template<class... Args>
uarray(Args&... args)
{
for (auto & v : c)
new(&v) _Ty(args...);
}
~uarray()
{
for (auto & v : c)
v.~_Ty();
}
};
#define BUF_SIZE 1024
intptr_t g_echo_count = 0;
future_vt RunEchoSession(tcp::socket socket)
{
std::size_t bytes_transferred = 0;
std::array<char, BUF_SIZE> buffer;
for(;;)
{
try
{
bytes_transferred += co_await socket.async_read_some(asio::buffer(buffer.data() + bytes_transferred, buffer.size() - bytes_transferred), rf_task);
if (bytes_transferred >= buffer.size())
{
co_await asio::async_write(socket, asio::buffer(buffer, buffer.size()), rf_task);
bytes_transferred = 0;
++g_echo_count;
}
}
catch (std::exception & e)
{
std::cerr << e.what() << std::endl;
break;
}
}
}
template<size_t _N>
void AcceptConnections(tcp::acceptor & acceptor, uarray<tcp::socket, _N> & socketes)
{
try
{
for (size_t idx = 0; idx < socketes.c.size(); ++idx)
{
go[&, idx]() -> future_vt
{
for (;;)
{
try
{
co_await acceptor.async_accept(socketes.c[idx], rf_task);
go RunEchoSession(std::move(socketes.c[idx]));
}
catch (std::exception e)
{
std::cerr << e.what() << std::endl;
}
}
};
}
}
catch (std::exception & e)
{
std::cerr << e.what() << std::endl;
}
}
void resumable_main_benchmark_asio_server()
{
using namespace std::literals;
asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 3456));
uarray<tcp::socket, 128> socketes(acceptor.get_io_service());
AcceptConnections(acceptor, socketes);
GO
{
for (;;)
{
g_echo_count = 0;
co_await 1s;
std::cout << g_echo_count << std::endl;
}
};
for (;;)
{
io_service.poll();
this_scheduler()->run_one_batch();
}
}
class chat_session : public std::enable_shared_from_this<chat_session>
{
public:
chat_session(asio::io_service & ios, tcp::resolver::iterator ep)
: socket_(ios)
, endpoint_(ep)
{
}
void start()
{
do_connect();
}
private:
void do_connect()
{
auto self = this->shared_from_this();
asio::async_connect(socket_, endpoint_,
[this, self](std::error_code ec, tcp::resolver::iterator iter)
{
if (!ec)
{
for (auto & c : write_buff_)
c = 'A' + rand() % 52;
do_write();
}
else
{
std::cerr << ec.message() << std::endl;
}
});
}
void do_read()
{
auto self(shared_from_this());
socket_.async_read_some(asio::buffer(read_buff_),
[this, self](const asio::error_code& ec, std::size_t size)
{
if (!ec)
{
do_write();
}
else
{
std::cerr << ec.message() << std::endl;
}
});
}
void do_write()
{
auto self(shared_from_this());
asio::async_write(socket_,
asio::buffer(write_buff_),
[this, self](std::error_code ec, std::size_t)
{
if (!ec)
{
do_read();
}
else
{
std::cerr << ec.message() << std::endl;
}
});
}
tcp::socket socket_;
tcp::resolver::iterator endpoint_;
std::array<char, BUF_SIZE> read_buff_;
std::array<char, BUF_SIZE> write_buff_;
};
void resumable_main_benchmark_asio_client(intptr_t nNum)
{
nNum = std::max((intptr_t)1, nNum);
try
{
asio::io_service ios;
asio::ip::tcp::resolver resolver_(ios);
asio::ip::tcp::resolver::query query_("127.0.0.1", "3456");
tcp::resolver::iterator iter = resolver_.resolve(query_);
for (intptr_t i = 0; i < nNum; ++i)
{
auto chat = std::make_shared<chat_session>(ios, iter);
chat->start();
}
ios.run();
}
catch (std::exception & e)
{
std::cout << "Exception: " << e.what() << "\n";
}
}

+ 149
- 146
librf/src/asio_task.h View File

@@ -1,150 +1,153 @@

#pragma once

#include "future.h"
#include "asio/detail/config.hpp"
#include <memory>

#include "asio/detail/push_options.hpp"
#include "asio/async_result.hpp"
#include "asio/error_code.hpp"
#include "asio/handler_type.hpp"
#include "asio/system_error.hpp"

namespace asio {

template<typename Allocator = std::allocator<void> >
class rf_task_t
{
public:
typedef Allocator allocator_type;
constexpr rf_task_t() {}
explicit rf_task_t(const Allocator& allocator) : allocator_(allocator) {}

template<typename OtherAllocator>
rf_task_t<OtherAllocator> operator[](const OtherAllocator& allocator) const {
return rf_task_t<OtherAllocator>(allocator);
}

allocator_type get_allocator() const { return allocator_; }
private:
Allocator allocator_;
};

//constexpr rf_task_t<> rf_task;
#pragma warning(push)
#pragma warning(disable : 4592)
__declspec(selectany) rf_task_t<> rf_task;
#pragma warning(pop)

namespace detail {

template<typename T>
class promise_handler
{
public:
using result_type_t = T;
using state_type = resumef::state_t<result_type_t>;

template<typename Allocator>
promise_handler(const rf_task_t<Allocator> &)

#pragma once
#include <asio.hpp>
#include "future.h"
#include <memory>
#include "asio/detail/push_options.hpp"
/*
#include "asio/detail/config.hpp"
#include "asio/async_result.hpp"
#include "asio/error_code.hpp"
#include "asio/handler_type.hpp"
#include "asio/system_error.hpp"
*/
namespace asio {
template<typename Allocator = std::allocator<int> >
class rf_task_t
{
public:
typedef Allocator allocator_type;
constexpr rf_task_t() {}
explicit rf_task_t(const Allocator& allocator) : allocator_(allocator) {}
template<typename OtherAllocator>
rf_task_t<OtherAllocator> operator[](const OtherAllocator& allocator) const {
return rf_task_t<OtherAllocator>(allocator);
}
allocator_type get_allocator() const { return allocator_; }
private:
Allocator allocator_;
};
//constexpr rf_task_t<> rf_task;
#pragma warning(push)
#pragma warning(disable : 4592)
__declspec(selectany) rf_task_t<> rf_task;
#pragma warning(pop)
namespace detail {
template<typename T>
class promise_handler
{
public:
using result_type_t = T;
using state_type = resumef::state_t<result_type_t>;
template<typename Allocator>
promise_handler(const rf_task_t<Allocator> &)
: state_(resumef::make_counted<state_type>())
{
}
void operator()(T t) const
{
state_->set_value(std::move(t));
}
void operator()(const asio::error_code& ec, T t) const
{
if (!ec)
{
state_->set_value(std::move(t));
}
else
{
state_->set_exception(std::make_exception_ptr(asio::system_error(ec)));
}
}
{
}
void operator()(T t) const
{
state_->set_value(std::move(t));
}
void operator()(const asio::error_code& ec, T t) const
{
if (!ec)
{
state_->set_value(std::move(t));
}
else
{
state_->set_exception(std::make_exception_ptr(asio::system_error(ec)));
}
}
resumef::counted_ptr<state_type> state_;
};
template<>
class promise_handler<void>
{
public:
using result_type_t = void;
using state_type = resumef::state_t<result_type_t>;
template<typename Allocator>
promise_handler(const rf_task_t<Allocator> &)
};
template<>
class promise_handler<void>
{
public:
using result_type_t = void;
using state_type = resumef::state_t<result_type_t>;
template<typename Allocator>
promise_handler(const rf_task_t<Allocator> &)
: state_(resumef::make_counted<state_type>())
{
}
void operator()() const
{
state_->set_value();
}
void operator()(const asio::error_code& ec) const
{
if (!ec)
{
state_->set_value();
}
else
{
state_->set_exception(std::make_exception_ptr(asio::system_error(ec)));
}
}
{
}
void operator()() const
{
state_->set_value();
}
void operator()(const asio::error_code& ec) const
{
if (!ec)
{
state_->set_value();
}
else
{
state_->set_exception(std::make_exception_ptr(asio::system_error(ec)));
}
}
resumef::counted_ptr<state_type> state_;
};
} // namespace detail
template<typename T>
class async_result<detail::promise_handler<T> >
{
public:
typedef resumef::future_t<T> type;
explicit async_result(detail::promise_handler<T> & h)
: task_(std::move(h.state_))
{ }
resumef::future_t<T> get() { return std::move(task_); }
private:
resumef::future_t<T> task_;
};
// Handler type specialisation for zero arg.
template<typename Allocator, typename ReturnType>
struct handler_type<rf_task_t<Allocator>, ReturnType()> {
typedef detail::promise_handler<void> type;
};
// Handler type specialisation for one arg.
template<typename Allocator, typename ReturnType, typename Arg1>
struct handler_type<rf_task_t<Allocator>, ReturnType(Arg1)> {
typedef detail::promise_handler<Arg1> type;
};
// Handler type specialisation for two arg.
template<typename Allocator, typename ReturnType, typename Arg2>
struct handler_type<rf_task_t<Allocator>, ReturnType(asio::error_code, Arg2)> {
typedef detail::promise_handler<Arg2> type;
};
template<typename Allocator, typename ReturnType>
struct handler_type<rf_task_t<Allocator>, ReturnType(asio::error_code)> {
typedef detail::promise_handler<void> type;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
};
} // namespace detail
template<typename T>
class async_result<detail::promise_handler<T> >
{
public:
typedef resumef::future_t<T> type;
explicit async_result(detail::promise_handler<T> & h)
: task_(std::move(h.state_))
{ }
resumef::future_t<T> get() { return std::move(task_); }
private:
resumef::future_t<T> task_;
};
// Handler type specialisation for zero arg.
template<typename Allocator, typename ReturnType>
struct handler_type<rf_task_t<Allocator>, ReturnType()> {
typedef detail::promise_handler<void> type;
};
// Handler type specialisation for one arg.
template<typename Allocator, typename ReturnType, typename Arg1>
struct handler_type<rf_task_t<Allocator>, ReturnType(Arg1)> {
typedef detail::promise_handler<Arg1> type;
};
// Handler type specialisation for two arg.
template<typename Allocator, typename ReturnType, typename Arg2>
struct handler_type<rf_task_t<Allocator>, ReturnType(asio::error_code, Arg2)> {
typedef detail::promise_handler<Arg2> type;
};
template<typename Allocator, typename ReturnType>
struct handler_type<rf_task_t<Allocator>, ReturnType(asio::error_code)> {
typedef detail::promise_handler<void> type;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"

+ 9
- 9
librf/src/sleep.h View File

@@ -16,29 +16,29 @@ namespace resumef
}
template<class _Rep, class _Period>
future_vt sleep_for(const std::chrono::duration<_Rep, _Period>& dt_, scheduler & scheduler_)
inline future_vt sleep_for(const std::chrono::duration<_Rep, _Period>& dt_, scheduler & scheduler_)
{
return std::move(sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), scheduler_));
return sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), scheduler_);
}
template<class _Rep, class _Period>
future_vt sleep_for(const std::chrono::duration<_Rep, _Period>& dt_)
inline future_vt sleep_for(const std::chrono::duration<_Rep, _Period>& dt_)
{
return std::move(sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), *this_scheduler()));
return sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), *this_scheduler());
}
template<class _Clock, class _Duration = typename _Clock::duration>
future_vt sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_, scheduler & scheduler_)
inline future_vt sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_, scheduler & scheduler_)
{
return std::move(sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), scheduler_));
return sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), scheduler_);
}
template<class _Clock, class _Duration>
future_vt sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_)
inline future_vt sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_)
{
return std::move(sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), *this_scheduler()));
return sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), *this_scheduler());
}
template <class Rep, class Period>
auto operator co_await(std::chrono::duration<Rep, Period> dt_)
inline future_vt operator co_await(std::chrono::duration<Rep, Period> dt_)
{
return sleep_for(dt_);
}

+ 10
- 10
tutorial/test_async_timer.cpp View File

@@ -15,19 +15,19 @@ void resumable_main_timer()
auto th = this_scheduler()->timer()->add_handler(system_clock::now() + 5s,
[](bool bValue)
{
if (bValue)
std::cout << "timer canceled." << std::endl;
else
std::cout << "timer after 5s." << std::endl;
});
{
if (bValue)
std::cout << "timer canceled." << std::endl;
else
std::cout << "timer after 5s." << std::endl;
});
auto th2 = this_scheduler()->timer()->add_handler(1s,
[&th](bool)
{
std::cout << "timer after 1s." << std::endl;
th.stop();
});
{
std::cout << "timer after 1s." << std::endl;
th.stop();
});
this_scheduler()->run_until_notask();

+ 6
- 1
vs_proj/librf.cpp View File

@@ -19,10 +19,15 @@ extern void resumable_main_channel_mult_thread();
extern void resumable_main_when_all();
extern void resumable_main_benchmark_mem();
extern void resumable_main_benchmark_asio_server();
extern void resumable_main_benchmark_asio_client(intptr_t nNum);
int main(int argc, const char * argv[])
{
resumable_main_sleep();
if (argc > 1)
resumable_main_benchmark_asio_client(atoi(argv[1]));
else
resumable_main_benchmark_asio_server();
return 0;
//resumable_main_resumable();

+ 12
- 12
vs_proj/librf.vcxproj View File

@@ -88,8 +88,8 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\librf;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await /permissive- </AdditionalOptions>
<AdditionalIncludeDirectories>..\librf;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
@@ -102,16 +102,16 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;RESUMEF_DEBUG_COUNTER=0;RESUMEF_ENABLE_MULT_SCHEDULER=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;ASIO_STANDALONE;RESUMEF_DEBUG_COUNTER=0;RESUMEF_ENABLE_MULT_SCHEDULER=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\librf;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await /permissive- </AdditionalOptions>
<AdditionalIncludeDirectories>..\librf;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MinimalRebuild />
<CLanguageStandard>c11</CLanguageStandard>
<CppLanguageStandard>c++1y</CppLanguageStandard>
<DisableLanguageExtensions>true</DisableLanguageExtensions>
<DisableSpecificWarnings>4834</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -126,8 +126,8 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\librf;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await /permissive- </AdditionalOptions>
<AdditionalIncludeDirectories>..\librf;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
@@ -145,9 +145,9 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\librf;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await /permissive- </AdditionalOptions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;ASIO_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\librf;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await</AdditionalOptions>
<ExceptionHandling>Sync</ExceptionHandling>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
@@ -157,7 +157,6 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<BufferSecurityCheck>false</BufferSecurityCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DisableLanguageExtensions>true</DisableLanguageExtensions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -169,6 +168,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\benchmark\benchmark_asio_echo.cpp" />
<ClCompile Include="..\benchmark\benchmark_async_mem.cpp" />
<ClCompile Include="..\librf\src\event.cpp" />
<ClCompile Include="..\librf\src\mutex.cpp" />

+ 3
- 0
vs_proj/librf.vcxproj.filters View File

@@ -100,6 +100,9 @@
<ClCompile Include="..\librf\src\when.cpp">
<Filter>librf\src</Filter>
</ClCompile>
<ClCompile Include="..\benchmark\benchmark_asio_echo.cpp">
<Filter>benchmark</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\librf\librf.h">

Loading…
Cancel
Save