0

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

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 秒,没有记录它不会变慢。

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

4

2 回答 2

1

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

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

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

于 2013-08-14T09:23:17.340 回答
0

请参阅此示例:如何为生产者和消费者使用工作队列(一对多)。很好解释。

于 2017-02-07T23:54:53.950 回答