我终于找到了我服务器的瓶颈,原来是async_write
,async_write_some
也是如此。
这里是以下基准代码:
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
//boost::asio::async_write(mMainData.mSocket, boost::asio::buffer(pSendBuff->pBuffer, pSendBuff->dwUsedSize), mMainData.mStrand.wrap(boost::bind(&CServer::WriteHandler, pServer, this, pSendBuff, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
mMainData.mSocket.async_write_some(boost::asio::buffer(pSendBuff->pBuffer, pSendBuff->dwUsedSize), (boost::bind(&CServer::WriteHandler, pServer, this, pSendBuff, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
clock_gettime(CLOCK_MONOTONIC, &end);
timespec temp;
if ((end.tv_nsec - start.tv_nsec) < 0)
{
temp.tv_sec = end.tv_sec - start.tv_sec - 1;
temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
}
else
{
temp.tv_sec = end.tv_sec - start.tv_sec;
temp.tv_nsec = end.tv_nsec - start.tv_nsec;
}
pLogger->WriteToFile("./Logs/Benchmark_SendPacketP_AsyncWrite.txt", "dwDiff: %.4f\r\n", (float)temp.tv_nsec / 1000000.0f);
输出:
-[2016.05.21 03:45:19] dwDiff: 0.0552ms
-[2016.05.21 03:45:19] dwDiff: 0.0404ms
-[2016.05.21 03:45:19] dwDiff: 0.0542ms
-[2016.05.21 03:45:20] dwDiff: 0.0576ms
这太慢了,因为它是一个游戏服务器,我需要在房间 channel 中广播数据包,一个 channel 有 300 名玩家,想象一下它对我的玩家造成的网络延迟。
当然这个测试是在服务器上只有我自己完成的。
是我的代码错了还是我在 ASIO 实现逻辑中遗漏了什么?
CXXFLAGS: -ggdb -ffunction-sections -Ofast -m64 -pthread -fpermissive -w -lboost_system -lboost_thread -Wall -fomit-frame-pointer
LDFLAGS: -Wl,-gc-sections -m64 -pthread -fpermissive -w -lboost_system -lboost_thread -lcurl
硬件是: 英特尔至强 E3-1231v3(4 核 8 线程) 64GB 内存 1GBPS 上行链路
我正在培养 8 名 ASIO worker 。
所以我用调试器进入 async_write 并发现了这个:
template <typename ConstBufferSequence, typename Handler>
void async_send(base_implementation_type& impl,
const ConstBufferSequence& buffers,
socket_base::message_flags flags, Handler& handler)
{
bool is_continuation =
boost_asio_handler_cont_helpers::is_continuation(handler);
// Allocate and construct an operation to wrap the handler.
typedef reactive_socket_send_op<ConstBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
boost_asio_handler_alloc_helpers::allocate(
sizeof(op), handler), 0 };
p.p = new (p.v) op(impl.socket_, buffers, flags, handler);
BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send"));
start_op(impl, reactor::write_op, p.p, is_continuation, true,
((impl.state_ & socket_ops::stream_oriented)
&& buffer_sequence_adapter<boost::asio::const_buffer,
ConstBufferSequence>::all_empty(buffers)));
p.v = p.p = 0;
}
为什么 boost::asio 在本应是高性能的库中调用“new”? 无论如何要预先创建它试图分配的内容? 抱歉,我无法分析内部结构,因为我使用 VisualGDB 和 Microsoft Visual Studio 进行开发,并在 VMWare 中运行 GCC 4.8.5 工具集。
最佳答案
我知道这个答案有点晚了,但我会发布它以防有人觉得有用。
确实,在发布完成处理程序时会调用 new。然而,官方文档解释了如何通过实现自定义内存管理来优化以避免相关的运行时开销。这是示例: custom memory management for completion handlers
关于c++ - Boost ASIO async_write_some 真的很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37358125/