生产者/消费者 - 使用高 CPU 的生产者
Posted
技术标签:
【中文标题】生产者/消费者 - 使用高 CPU 的生产者【英文标题】:Producer / Consumer - Producer using high CPU 【发布时间】:2014-02-26 19:39:08 【问题描述】:我有一个消费者作为生产者消费者模式的一部分:
简化:
public class MessageFileLogger : ILogger
private BlockingCollection<ILogItem> _messageQueue;
private Thread _worker;
private bool _enabled = false;
public MessageFileLogger()
_worker = new Thread(LogMessage);
_worker.IsBackground = true;
_worker.Start();
private void LogMessage()
while (_enabled)
if (_messageQueue.Count > 0)
itm = _messageQueue.Take();
processItem(itm);
else
Thread.Sleep(1000);
如果我删除了
Thread.Sleep(1000);
将线程设置为睡眠状态时,CPU 使用率从 0% 攀升至极高 (13%)。
另外,如果我实例化该类的多个实例,每个实例的 CPU 使用率都会增加 13%。
大约每分钟左右(可能每 30 秒)将一个新的 LogItem 添加到 BlockingCollection,并将适用的消息写入文件。
是否有可能线程以某种方式阻塞了其他线程的运行,而系统需要以某种方式进行补偿?
更新: 更新代码以更好地反映实际代码
【问题讨论】:
即使队列中没有任何内容,您发布的代码也会处理项目。 【参考方案1】:您指定了要运行的线程代码,因此默认情况下,它会在单个逻辑核心上尽可能快地运行该代码(while 循环)。因为这大约是 13%,我想你的 CPU 有 4 个超线程内核,从而产生 8 个逻辑内核。每个线程在其核心上尽可能快地运行它的 while 循环,从而导致另外 13% 的使用率。真的很简单。
不使用睡眠的副作用是整个系统运行速度变慢,并且使用/产生更多的电池/热量。
一般来说,正确的方法是给_messageQueue
另一个方法,比如
bool BlockingCollection::TryTake(type& item, std::chrono::milliseconds time)
DWORD Ret = WaitForSingleObject(event, time.count());
if (Ret)
return false;
item = Take(); //might need to use a shared function instead of calling direct
return true;
那么你的循环很简单:
private void LogMessage()
type item;
while (_enabled)
if (_messageQueue.Take(item, std::chrono::seconds(1)))
;//your origional code makes little sense, but this is roughly the same
processItem(itm);
这也意味着,如果在阻塞部分的任何时候添加了一个项目,它会立即执行,而不是一秒钟后。
【讨论】:
是的,我确实注意到我的风扇打开得很快。添加 Thread.Sleep 方法是常见的解决方案吗?如果不是,您能否指出正确的做事方式? @TruthOf42:添加到答案以上是关于生产者/消费者 - 使用高 CPU 的生产者的主要内容,如果未能解决你的问题,请参考以下文章