C++ While loop, usleep()/sleep() how not to use 90% of CPU? (Ubuntu 12.04)

ChumbiChubaGo picture ChumbiChubaGo · Apr 12, 2014 · Viewed 16.8k times · Source

Suppose I have C++ code such as

#include "myheaderfiles.h"
//..some stuff
//...some more stuff
int main()
{
   double milliseconds;
   int seconds;
   int minutes;
   int timelimit=2;
   ...
   ...
   //...code here that increments 
   //.....milliseconds,seconds, and minutes

   while(minutes <=timelimit)
   {
      //...do stuff
      if(milliseconds>500)
      {
         //...do stuff 
         //...every half second
      } //end if
   } //end while
}//end main

The program will run fine and does what its supposed to do but it will use up 90%+ of my cpu.

It was suggested to me to use usleep() in my while loop ever 100ms or so since I really only care about doing stuff every 500ms anyway. That way, it hog the CPU when its not needed.

So I added it to my while loop like so

   while(minutes <=timelimit)
   {
      //...do stuff
      if(milliseconds>500)
      {
         //...do stuff 
         //...every half second
      } //end if
      usleep(100000);
   } //end while

It compiles fine, but when I run it, the program will hang right at usleep and never return. I read somewhere that before calling usleep, one needs to flush all buffers, so I flushed all file streams and couts etc etc. Still no luck.

I've searched for 2 days for a solution. I've used sleep() too, with no luck.

I found a few alternatives but they seem complicated and will add a lot of code to my program that I dont really fully understand which will complicate it and make it messy, plus it might not work.

I never really put too much thought in my while() loops before because most of the programs I wrote were for microcontrollers or FPGAs which is no problem to hog the processor.

If anyone can help.... any resources, links,books? Thanks.

Answer

Damon picture Damon · Apr 22, 2014

Your approach somewhat comes from the wrong end. A program should consume 90-100% CPU as long as it has something useful to do (and it should block otherwise, consuming zero CPU).
Sleeping in between will cause execution being longer for no good reason, and consume more energy than just doing the work as fast as possible (at 100% CPU) and then completely blocking until more work is available or until some other significant thing (e.g. half a second has passed, if that matters for you) happens.

With that in mind, structure your program in a way conceptually like:

while(blocking_call() != exit_condition)
{
    while(have_work)
        do_work();
}

Also, do not sleep during execution, but use timers (e.g. setitimer) to do something at regular intervals. Not only will this be more efficient, but also a lot more precise and reliable.

How exactly you implement this depends on how portable you want your software to be. Under Ubuntu/Linux, you can for example use APIs such as epoll_wait with eventfd rather than writing a signal handler for the timer.