如何提高Boost ASIO的吞吐量,UDP客户端应用程序

5
我正在使用Boost ASIO库实现一个Windows UDP客户端,需要具备高吞吐量。我想使用异步接收调用,以便最终实现接收超时,即在一定时间内如果没有接收到数据报文,我的应用程序将退出。
我的问题是,使用同步接收相对于异步接收,我看到了30%的更高数据吞吐量。当我在多个Dell R630、R710 Windows 2008服务器和甚至我的Lenovo ThinkPad笔记本电脑上运行应用程序时,我观察到了这个问题。
下面两段代码之间的主要性能差异是什么?每个异步接收后调用ioService.run_one()是否有更多开销?我是Boost库的新用户,所以任何帮助都将不胜感激!
同步接收:
socket_->receive_from(boost::asio::buffer(&vector_[0], datagramSize),  
                      endPoint_);

与同步接收相比,异步接收(阻塞):

err = boost::asio::error::would_block;

socket_->async_receive_from(
    boost::asio::mutable_buffers_1(&vector_[0], datagramSize),
    endPoint_,
    boost::bind(&HandleRead, _1, _2, &err, &bytesReceived));

do
{
    ioService_.run_one()
}
while(err == boost::asio::error::would_block)

异步接收处理程序函数:

static void HandleRead
(
    const boost::system::error_code& error, 
    std::size_t bytesRead,
    boost::system::error_code* outError, 
    std::size_t* outBytesRead
)
{
    *outError = error;
    *outBytesRead = bytesRead;
}

在您的async_receive_from案例中,handler使用缓慢的标准operator new进行分配。使用快速的自定义分配可以提高性能。 - Evgeny Panasyuk
1个回答

7
< p >“async_”系列API函数的最重要属性是它们以异步方式运行,这一点并不令人惊讶。

仅仅运行任何东西异步地本身并不能使其更快。实际上,由于调度问题,它可能会更慢。

异步性可以让你在少量线程(例如主线程)上做更多的事情。

听起来好像您的应用程序并不需要这种复用操作。如果您的应用程序确实以线性方式尽可能快地消耗单个数据包源,则逐项进行以下操作是没有意义的:

  • 插入一个(线程安全的)任务队列
  • 要求io_service将任务跨可用服务线程¹调度(您只有一个)
  • 通过回调形式协调结果; 回调经常导致对象生命周期存在问题,这又经常导致shared_ptr<>,如果是这样,这些都是更多延迟的来源(由于减少了引用的局部性,动态分配等)。

如果您不需要异步模式,请勿使用它。

即使您有数量有限的基本上是单线程的顺序运行任务,您也可以通过为每个任务使用一个线程,每个线程使用一个io_service,并避免协调来实现最佳效果。

¹运行io_service :: run或类似内容的线程


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接