【问题标题】:Log queue in multithreaded application多线程应用程序中的日志队列
【发布时间】:2013-08-14 07:33:43
【问题描述】:

我编写了一个在单独线程中工作的网络记录器。这个想法是允许应用程序推送任何数量的数据,并且记录器应该单独处理它而不减慢主线程。伪代码如下:

void LogCoroutine::runLogic()
{
    mBackgroundWorker = std::thread(&LogCoroutine::logic, this);
    mBackgroundWorker.detach();
}

void LogCoroutine::logic()
{
    while (true)
    {
        _serverLogic();
        _senderLogic();

        std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 10ms
    }
}

void LogCoroutine::_senderLogic()
{
    std::lock_guard<std::mutex> lock(mMutex);    

    while (!mMessages.empty() && !mClients.empty())
    {
        std::string nextMessage = mMessages.front();
        mMessages.pop_front();

        _sendMessage(nextMessage);
    }
}

_serverLogic 检查新连接(对等点)的套接字,_senderLogic 处理队列中的消息并将其发送给所有连接的对等点。

最后一个功能:推送消息:

void LogCoroutine::pushMessage(const std::string& message)
{
    std::lock_guard<std::mutex> lock(mMutex);
    mMessages.push_back(message);
}

当包裹不经常发送时,一切都很好。应用程序启动时有一个循环记录大量信息。并且应用程序挂起 5-10 秒,没有记录它不会变慢。

那么,这个架构的瓶颈在哪里?也许在里面推送带有互斥锁的每条消息是个坏主意?

【问题讨论】:

  • 当我在 while(true) 循环中看到 sleep_for 时,我忍不住尖叫……为什么不用 std::condition_variable 来代替?如果我是你,我会创建一个线程安全的队列类,而不是在 logger 类中使用互斥锁
  • 为什么不准备一个经过测试的消息队列,即ØMQ。有一次,我创建了an example,它只显示了原理,因为您的代码正在尝试。但是还有更多需要注意的地方:您的硬盘驱动器 io 是否因为它也在等待它而阻塞了应用程序的其余部分,或者您可能想从多个客户端通过网络登录等等。我建议查看 ØMQ .您甚至可以使用它在进程内进行通信。所有消息传递都是异步完成的。如果您登录速度过快,请注意排队人数过多
  • @Kek,即参见g2log,它基于无锁队列:)。把它和消息队列结合起来大概就是作者想要达到的目的
  • @DmitryLedentsov:在记录的情况下,您可能应该在队列上定义最大大小并决定是否在溢出的情况下丢弃传入的日志(比覆盖现有日志简单得多,因为这些通常是域发件人)。
  • @MatthieuM.:也许,是的,无论如何。如果有人认真对待它,那么负载平衡网络架构可能会有所帮助。在 0mq 中有一些dropping or offloading messages的配置选项

标签: c++ multithreading


【解决方案1】:

您的方法基本上是以一定间隔(10 毫秒)轮询日志事件。这种方法(实际上是忙于等待)的性能不是很好,因为即使没有任何日志消息,您也总是会消耗一些 CPU。另一方面,如果有新消息到达,您不会通知等待线程。

我建议使用某种blocking queue 来解决这两个问题。内部阻塞队列具有互斥锁和条件变量,因此当队列为空时,消费者线程正在等待(不是忙循环!)。我认为您的用例非常适合阻塞队列。您可以非常轻松地基于互斥量 + 条件变量实现自己的队列。

使用互斥锁推送每条消息并不是一个坏主意,无论如何你都必须同步它。我只是建议摆脱民意调查。

【讨论】:

    【解决方案2】:

    See this example: 如何为生产者和消费者使用工作队列(一对多)。解释得很好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-14
      • 1970-01-01
      • 2013-02-13
      • 1970-01-01
      • 1970-01-01
      • 2020-02-01
      • 1970-01-01
      相关资源
      最近更新 更多