我写了一个网络记录器,它在单独的线程中工作。这样做的目的是允许应用程序推送任意数量的数据,而记录器应该在不减慢主线程的情况下分别处理数据。伪码看起来像:
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秒,没有登录就不会慢下来。
那么,这个体系结构的瓶颈在哪里呢?也许把每一条带互斥的信息都推进去是个坏主意?
发布于 2013-08-14 09:23:17
您的方法基本上是轮询具有一定间隔(10 ms)的日志事件。这种方法(实际上是忙于等待)并不是很好的性能,因为即使没有任何日志消息,您也总是消耗一些CPU。另一方面,如果新消息到达,则不通知等待线程。
我建议使用某种阻塞队列来解决这两个问题。内部阻塞队列有互斥和条件变量,因此使用者线程正在等待(不是繁忙的循环!)而队列是空的。我认为您的用例非常适合阻塞队列。您可以非常容易地基于互斥+条件变量实现您自己的队列。
用互斥推动每条消息并不是一个坏主意,无论如何你必须同步它。我只想建议取消投票。
发布于 2017-02-07 23:54:53
参见此示例:如何为生产者和消费者使用工作队列(1对多)。解释得很好。
https://stackoverflow.com/questions/18225726
复制相似问题