提升ASIO IO_SERVICE实施?

use*_*156 8 multithreading boost thread-safety boost-asio threadpool

我正在编写一个异步日志记录框架,我有多个线程转储数据.我开始玩Boost asio,因为它提供了一些简单的方法来强制执行序列化和排序.由于我是初学者,我开始使用线程安全(使用boost::mutexboost:condition_variable)圆形bounded_buffer(实际上是矢量)进行设计.

我写了一个简单的小基准来测量性能.基准测试只是记录一百万条消息的单个线程(将其推入缓冲区),我的工作线程只是从队列中获取消息以记录到文件/控制台/记录器列表.(PS互斥和CV的使用是正确的,并且指向消息的指针正在被移动,因此从这个角度看,一切都很好/有效).

当我改变我的实现而不是使用boost::asio::io_service和使用单个线程执行时run(),性能确实得到了提升(实际上它在增加记录的消息数量方面非常好,而不是在我的初始简单模型中降低性能)

以下是我想澄清的几个问题.

  1. 为什么性能提升?(我认为boost::asio::io_service内部实现具有处理程序的线程安全队列,这使得它比我自己的初始简单线程安全队列设计更有效).请注意我的设计经过了很好的审核,并且没有任何错误(骨架代码基于经过验证的示例),有人可以更详细地了解如何io_service实现这一点的内部细节.

  2. 第二个有趣的观察是,在增加线程时,我的初始实现性能得到了改善,但是以丢失序列化/排序为代价,但是使用boost :: asio降低了性能(非常轻微)(我认为这是因为我的处理程序正在执行非常简单的任务并且上下文切换开销正在降低,我将尝试提出更复杂的任务并在稍后发布我的观察结果).

  3. 我真的想知道是否boost::asio只是用于i/o和网络操作,还是我使用它来通过线程池进行并发任务(并行)是一种很好的设计方法.难道io_service只是意味着对象用于I/O对象(如写入文件),但我发现这是一个非常有趣的帮助我解决并发任务(不只是I/O或网络相关)的序列化的方式方法(有时是强制排序使用股线).我是新手,并且非常好奇为什么基本模型没有像我使用boost asio那样执行/扩展.

结果:(我只有1个工作线程)

  • 1000任务:两种情况下都是10微秒/任务
  • 10000任务:80微秒(有界缓冲),10微秒增强asio
  • 100000任务:250微秒(bounde缓冲区),10微秒增强asio

知道boost如何解决io_service处理程序的线程安全队列中的线程安全问题会很有趣(我总是认为在某些实现级别它们也必须使用锁和cv).

Ocu*_*mer 4

恐怕我对(1)无能为力,但对于其他两个问题:

(2) 我发现架构中存在一些boost::asio不确定的开销,即数据传入(或发送到 IO 服务对象)之间的延迟可能从几乎即时响应到数百个数量级不等毫秒。我试图将其量化,作为我试图解决的有关记录和时间戳 RS232 数据的另一个问题的一部分,但尚未获得任何结论性的结果或稳定延迟的方法。如果发现上下文切换组件存在类似问题,我一点也不感到惊讶。

(3) 就用于异步I/O以外的任务而言boost::asio,它现在是我用于大多数异步操作的标准工具。我boost::asio一直使用计时器来进行异步进程,并为其他任务生成超时。将多个工作线程添加到池中的能力意味着您也可以针对其他异步高负载任务很好地扩展解决方案。我去年编写的最简单也是最喜欢的类是一个用于boost::asioIO 服务的小型工作线程类(如果有任何拼写错误,请道歉,这是凭记忆抄写的,而不是剪切和粘贴的):

class AsioWorker
{
public:
  AsioWorker(boost::asio::io_service * service):
  m_ioService(service), m_terminate(false), m_serviceThread(NULL)
  {
    m_serviceThread = new boost::thread( boost::bind( &AsioWorker::Run, this ) )
  }
  void Run( void )
  {
    while(!m_terminate)
      m_ioService->poll_one();
      mySleep(5); // My own macro for cross-platform millisecond sleep
  }
  ~AsioWorker( void )
  {
    m_terminate = true;
    m_serviceThread->join();
  }
private:
  bool m_terminate;
  boost::asio::io_service *m_ioService;
  boost::thread *m_serviceThread;
}
Run Code Online (Sandbox Code Playgroud)

这个类是一个很棒的小玩具,只需new根据需要添加一些,delete当你用完它们时添加一些。将 a 添加std::vector<AsioWorker*> m_workerPool到使用的设备类中boost::asio,您可以进一步包装线程池管理内容。我一直想根据适当增长线程池的时间来编写一个智能池自动管理器,但我还没有一个需要它的项目。

为了满足您对线程安全的好奇心,可以深入研究 boost 的内部,以准确了解它们是如何做它们正在做的事情的。就我个人而言,我总是从表面上看待大部分增强功能,并根据过去的经验认为它在幕后进行了相当好的优化。