我终于找到了服务器的瓶颈,结果是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
这是一个非常慢的游戏服务器,我需要在房间频道中广播数据包,在1个频道中有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
硬件是: Intel Xeon E3-1231v3(4核,8线程) 64GB RAM 1GBPS上行链接
我正在产生8名ASIO工作人员。
所以我用调试器踩到了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”? 无论如何要预先创建它试图分配的内容吗? 抱歉,我无法使用Visual Studio与Microsoft Visual Studio进行内部开发,并在VMWare中运行GCC 4.8.5工具集。
答案 0 :(得分:0)
如果没有分析器,试图确定哪个指令是瓶颈可能是对耐心的徒劳考验。创建最小示例可以帮助识别特定环境中的问题来源。例如,在既没有I / O争用也没有io_service
争用的受控场景中,我在使用native write()
和Asio's async_write()
时观察到0.015ms~写入。
试图解决的问题是以最小延迟向300个对等体写入相同的消息。一种解决方案可能是并行化问题:考虑使用并行运行的n
个作业,而不是单个作业将消息串行写入300个对等,并将消息串行写入300/n
个对等体。粗略估计一下:
write()
时观察到的平均值),则最后一次写入将在第一次写入后的4.485ms开始。根据上述估计,通过并行解决问题,即使每个asyc_write
个操作所花费的时间超过预期,也需要花费一半的时间来写入300个对等体。请记住,这些都是粗略估计,需要进行分析以确定理想的并发数量,并确定潜在的瓶颈。
答案 1 :(得分:0)
我知道这个答案有点晚了,但是我发布它以防有人发现这个有用。
确实在发布完成处理程序时会调用new。但是,官方文档解释了如何进行优化,以便通过实现自定义内存管理来避免相关的运行时开销。这是一个例子: custom memory management for completion handlers