Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I need to wait for short intervals of time in my program, but I really don't want to include unistd.h just to use sleep, so I'm doing it this way:

int main()
{
for(int i=0; i<=100000000000; i++); // <----- note that the loop doesn't do anything 
return 0;
}

I do this when I don't really have a specific interval to set for sleep.

Is there anything wrong with this? Would this harm the program in any way?

In C I know that if I did include unistd.h, and that if I used sleep(), that the following code would also make the program wait for a short interval of time:

int main()
{
sleep(2000); //or whatever the number (in milliseconds)
return 0;
}
share|improve this question
6  
14  
Do you have any actual reason for not wanting to type "#include <unistd.h>"? –  David Richerby Feb 22 at 21:54
5  
Using 100000000000 for an int is not very portable, some compilers wouldn't like it. –  QuentinUK Feb 23 at 4:09
1  
I did the same with a program and it nearly killed the computer. Internally, sleep will take the load off the program and put it really to sleep. –  Noah Feb 23 at 6:29

7 Answers 7

up vote 46 down vote accepted

The biggest problem with using a for-loop to do this is that you are wasting CPU power.

When using sleep, the CPU can, in a sense, take a break (hence the name "sleep") from executing your program. This means that the CPU will be able to run other programs that have meaningful work to do while your program waits.

But in the for-loop the CPU continuously have to do work to increase a variable. For what purpose? Nothing. But the CPU doesn't know that. It's told to increase the variable, so that's what it will do. Meanwhile, other programs aren't given as much time to do their work because your program is taking up time.

Please don't waste CPU power, use the sleep approach.

share|improve this answer
39  
In addition, the compiler may optimize out an empty loop, and the attempt to pause may be lost –  atk Feb 22 at 19:45
    
In further addition, if the compiler left it, it would be bad for scheduling, since the scheduler will see for as a long but active process. –  Ollie Ford Feb 22 at 23:08
    
@Simon, your answer seemed to me to gloss over what's happening internally, so I edited in a bit more detail. Are you OK with the changes? –  Kevin Feb 23 at 0:15
    
@Kevin Although I think other answers complete some of that information, your edit was welcome. Thanks. –  Simon André Forsberg Feb 23 at 0:17
    
@Simon No problem. Thanks for getting back to me! –  Kevin Feb 23 at 0:18

Back in the day, home computers used to have a “turbo” button, which (when activated), made the processor slower. The problem was that games were coded around an input loop that was expected to take a specific number of milliseconds. If the loop was executed faster, the whole game would speed up, becoming unplayable.

Today, computers have vastly different speeds and performance characteristics, so NOPping isn't reliable in any way (will it take half a second? half a year?). Furthermore, compilers are generally free to remove code that doesn't do anything – compiling your snippet under -O3 would hopefully remove that loop.

Don't use an ugly kludge just to achieve better compilation speed. Do it right – consider yourself a code craftsman, not a code monkey (no offense, rolfl).

share|improve this answer
5  
No offense taken... ;-) –  rolfl Feb 22 at 18:37
1  
+1 most compilers will simply remove this loop –  Luke McGregor Feb 23 at 1:06
    
Eh, my computer is fairly recent and have a Turbo button. However it behaves differently, it does a soft overclock on the GPU. –  Pierre-Luc Pineault Feb 23 at 5:46

This is called 'busywaiting' or 'spinning', and will work but has the following disadvantages:

  1. It will perform 'work' on your program instead of yielding control to OS and other programs - so it doesn't "play nice" with others; on a common computer there are many programs running at the same time that could also like to use that CPU instead.

  2. Busywaiting creates unneeded load on CPU, preventing it from idling - this results in extra heat, fan noise and lower battery life on laptop computers or mobile devices.

  3. The delay is unpredictable - it will vary greatly depending on the computer and also the compiler, which may "optimize it away" to no delay at all, as other answers noted.

In short - it will function, so if it's a one-off script for your own use then it can be okay, but if it's code meant for production use or something that will need to be maintained in the future, then don't do it this way.

share|improve this answer
    
+1 for the mention of battery impact, a relatively significant issue when so much computing is done on mobile devices these days. –  Barmar Feb 23 at 3:26

This technic is called Spinlock or busy waiting. It is implemented for example in Oracle database software to coordinate access to memory structures between different processes (latches).

It seems to be useful if the overhead of sleeping which results from context switching is larger than waste of CPU time when spinning. This is the case if the expected wait time is very short. Very short means some clock cycles and is far less than 2000 ms that you use in your example.

The compiler will not optimize the loop away if it is implemented correctly. This C example using a volatile variable is from busy waiting .

...
volatile int i=0;
...
while (i==0);
...

volatile tells the compiler that the value of the variable i can be changed from outside the current thread and so the compiler does not throw away the while-loop.

Busy waiting is listed as antipattern here. So you should not use it if you are not completely aware of its consequences.

Trying to avoid the inclusion of unistd.h seems not to be a valid reason to use busy waiting.

share|improve this answer

Two big reasons why that's a bad idea:

  1. The time spent on a given loop is very dependent on the computer running it. Ever played Quake on a modern computer? The frame rates are through the roof, and I hope that's not a surprise. More powerful computers can perform more calculations in a set time. If your computer takes 10 seconds to complete a loop, a more powerful computer might finish in 5 or less, and an older computer might take significantly longer.

    So, couldn't I just do this?

    #include <Mmsystem.h> //timeGetTime
    void Stall(unsigned long ms)
    {
        unsigned long start = timeGetTime();
        unsigned long passed = 0;
        while (passed < ms)
        passed = timeGetTime() - start;
    }
    

    Yeah, that would ensure that the same time is taken to finish the function. But don't get too excited; I said two big reasons.

  2. Sleep functions set your thread in a sort of "do not disturb" state, allowing your operating system to perform other tasks (handling other threads, cleaning up your thread) while your thread daydreams. While a human could look at the line and interpret it as "do nothing", your computer is wasting power blowing through that empty loop as fast as it can.

    So, I can do this?

    #include <Mmsystem.h> //timeGetTime
    #include <WinBase.h> //Sleep
    void Stall(unsigned long ms)
    {
        unsigned long start = timeGetTime();
        unsigned long passed = 0;
        while (passed < ms)
        {
            passed = timeGetTime() - start;
            Sleep(0);
        }
    }
    

    Better, but it still wastes CPU resources when it doesn't have to. And if there are no other threads running, Sleep(0) immediately returns to your thread, meaning your CPU is still running at maximum speed.

Conclusion: for most applications, stick with sleep functions.

share|improve this answer

The other answers here address the specific issues with your loop, and hopefully have convinced you that it is not the right approach. I want to comment on your motivations.

Why do you want to avoid unistd.h? It is entirely reasonable to include a header for just one function, and in the vast majority of cases there is no compelling reason not to.

If you are concerned about portability, just do something like this:

#if defined(__linux__)
#  include <unistd.h>
#elif defined(_WIN32)
#  include <windows.h>
#  define sleep(s) Sleep((s)*1000)
#endif

Then use sleep(seconds) everywhere.

share|improve this answer

The biggest single issue with this approach, other than eating processor cycles, is that the for loop will be removed by the optimiser if you enable any level of optimisation in the compiler. Suddenly you find that code that ran just fine in debug mode, stops working.

share|improve this answer
    
That is no really a valid argument against the usage of this technic. If programmed carefully this probleem can be avoided. Here is a discussion about avoiding optimization for a piece of code when using gcc: stackoverflow.com/questions/2219829/… help –  miracle173 Feb 23 at 22:02

protected by rolfl Feb 23 at 16:10

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.