Producer / Consumer - Producer using high CPU

。_饼干妹妹 提交于 2019-12-11 08:20:46

问题


I have a consumer as part of the producer consumer pattern:

simplified:

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);
            }
        }
    }
}

If I remove the

Thread.Sleep(1000);

The CPU usages climbs to something extremely high (13%) as opposed to 0%, with setting the thread to sleep.

Also, if I instantiate multiple instances of the class, the CPU usage climbs in 13% increments, with each instance.

A new LogItem is added the BlockingCollection about every minute or so (maybe every 30 seconds), and writes an applicable message to a file.

Is it possible that the thread is somehow blocking other threads from running, and the system somehow needs to compensate?

Update: Updated code to better reflect actual code


回答1:


You gave the thread code to run, so by default it runs that code (the while loop) as fast as it possibly can on a single logical core. Since that's about 13%, I'd imagine your CPU has 4 hyperthreaded cores, resulting in 8 logical cores. Each thread runs it's while loop as fast as it possibly can on it's core, resulting in another 13% usage. Pretty straightforward really.

Side effects of not using sleep are that the whole system runs slower, and uses/produces SIGNIFICANTLY more battery/heat.

Generally, the proper way is to give the _messageQueue another method like

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;
}

Then your loop is easy:

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);
    }
}

It also means that if an item is added at any point during the blocking part, it's acted on immediately instead of up to a full second later.



来源:https://stackoverflow.com/questions/22051545/producer-consumer-producer-using-high-cpu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!