【问题标题】:multi-producers/consumers performance多生产者/消费者表现
【发布时间】:2012-11-14 10:13:13
【问题描述】:

我编写了一个 SharedQueue,旨在与多个生产者/消费者一起工作。

class SharedQueue : public boost::noncopyable
{
public:
  SharedQueue(size_t size) : m_size(size){};
  ~SharedQueue(){};

  int count() const {return m_container.size();};
  void enqueue(int item);
  bool enqueue(int item, int millisecondsTimeout);

private:
  const size_t m_size;
  boost::mutex m_mutex;
  boost::condition_variable m_buffEmpty;
  boost::condition_variable m_buffFull;

  std::queue<int> m_container;
};

void SharedQueue::enqueue(int item)
{
  {
    boost::mutex::scoped_lock lock(m_mutex);
    while(!(m_container.size() < m_size)) 
    {
      std::cout << "Queue is full" << std::endl;
      m_buffFull.wait(lock);
    }
    m_container.push(item);
  }
  m_buffEmpty.notify_one();
}

int SharedQueue::dequeue()
{
  int tmp = 0;
  {
    boost::mutex::scoped_lock lock(m_mutex);

    if(m_container.size() == 0) 
    {
      std::cout << "Queue is empty" << std::endl;
      m_buffEmpty.wait(lock);
    }

    tmp = m_container.front();
    m_container.pop();
  }

  m_buffFull.notify_one();
  return tmp;
}


SharedQueue Sq(1000);


void producer()
{
  int i = 0;
  while(true)
  {
    Sq.enqueue(++i);
  }
}

void consumer()
{
  while(true)
  {
    std::cout  << "Poping: " << Sq.dequeue() << std::endl;
  }
}

int main()
{

  boost::thread Producer(producer);
  boost::thread Producer1(producer);
  boost::thread Producer2(producer);
  boost::thread Producer3(producer);
  boost::thread Producer4(producer);

  boost::thread Consumer(consumer);

  Producer.join();
  Producer1.join();
  Producer2.join();
  Producer3.join();
  Producer4.join();

  Consumer.join(); 

  return 0;
}

如您所见,我使用 boost::condition_variable。有没有办法让性能更好?也许我应该考虑任何其他同步方法?

【问题讨论】:

  • 你如何衡量“性能”?
  • 乍得,我的意思是从将数据放入队列和从中取出数据之间的时间。
  • 这是你的瓶颈吗?
  • 使用锁,一次只有一个生产者/消费者可以与您的队列对象交互。删除条件变量可确保它们中的每一个都尽可能快地进入锁。不过,这可能会导致饥饿。编写高性能代码很难 :) 我真的建议在重新发明轮子之前研究现有工具。
  • @D_E,恐怕如果您有大约 100 个线程,那么队列设计是您的性能问题中最少的(除非您运行在具有 32 个以上内核的非常胖的服务器上,在这种情况下,100 个线程是可以的)。

标签: c++ multithreading performance boost


【解决方案1】:

在真实场景而非综合测试中,我认为您的实现已经足够好。

但是,如果您希望每秒执行 106 次或更多操作,并且您正在为 Windows 进行开发,那么您的解决方案并不是那么好。

  1. 在 Windows 上,当您使用多线程类时,传统上 Boost 非常糟糕。 对于互斥体,CriticalSection 对象通常要快得多。对于 cond.vars, boost 的作者正在重新发明轮子,而不是使用 correct Win32 API

  2. 在 Windows 上,我希望称为“I/O 完成端口”的本机多生产者/消费者队列对象比任何可能的用户模式实现更有效数倍。它的主要目标是 I/O,但是调用 PostQueuedCompletionStatus API 将任何你想要的东西发布到队列中是完全可以的。唯一的缺点——队列没有上限,所以必须自己限制队列大小。

【讨论】:

    【解决方案2】:

    这不是您问题的直接答案,但它可能是一个不错的选择。

    根据你想提高多少性能,可能值得看看Disruptor Patternhttp://www.2robots.com/2011/08/13/a-c-disruptor/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-24
      • 2015-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多