Quote Originally Posted by Clootie
Can you explain why you think that Sleep(1) is not proper way to cut down on cpu?
I don't have a problem with Sleep in general, its peoples lack of understanding of what Sleep actually does, and how to implement it. I'd argue against ever using Sleep(1+).

I'll admit, that calling sleep inside of a thread is quite common (outside of Real Time stuff). I'll also admit to calling Sleep(0) inside of my game loops to lower CPU head (notice I didn't say Sleep(1)). My problem with sleep isn't in these situations, its in the situation where the developer doesn't understand what is going to come from them doing it. Sleep(0) achieves your lowered CPU by simply telling the system to go ahead and process others, then return to me. Sleep(1) tells the system to wait AT LEAST 1ms.

First off is that sleep can't be canceld, once called you are forced into the wait. This means that on a slower system where a different down time may be necessary it won't be achieved properly. Utilizing it inside of the main loop of some applications may work just fine it still breaks this area. Sleep is not definitive, calling Sleep(1) inside the loop may allow another heavy weight application (or thread) to take over and hold you out of the loop. Thus a Sleep(1) may come close to a Sleep(2+), not a big deal until you add that up a few thousand times. Sleep(0) doesn't require the test for greater, nor the call to the processor timer, thus has a lower call time.

The largest problem with using Sleep is that people don't realize that you had it inside of a large loop. Thus they turn around and use it inside of a tight loop and wonder why they get inconsistent results on different systems. Code such as the following pops up:

Proper - Origional code
[pascal]begin
while(true) do
begin
// Calculate frame difference
// Game Code
sleep(0);
end;
end;[/pascal]


Acceptable - Minor "Tweak" cuz they thought it was right
[pascal]begin
while(true) do
begin
// Calculate frame difference
// Game Code
sleep(1);
end;
end;[/pascal]


Bad Idea - Hmmm... Need more time between frames, this should work
[pascal]begin
while(true) do
begin
StartFrame := GetTickCount;
// Game Code
while GetTickCount-StartFrame < 100 do // Supposidly 10 FPS
sleep(1);
end;
end;[/pascal]

Yes, vetrans know that this is a horrid idea, we know why, and we know how to fix it. But the novice that looked at our code didn't know it. They saw something similar and thus decided that the code above was a good idea.

In fact, I've seen tutorials and demos written with "Delay" routines that are bound to ProcessMessages and Sleep. I can write code that achieves the same thing with about 1/2 of the overhead.

Even Worse (but unfortunately common, but quoted as being a proper delay sequence) - Hey I need a proper dealy routine, this looks right
[pascal]procedure Delay(dwMilliseconds: Longint);
var
iStart, iStop: DWORD;
begin
iStart := GetTickCount;
repeat
iStop := GetTickCount;
Application.ProcessMessages;
Sleep(1);
until (iStop - iStart) >= dwMilliseconds;
end;[/pascal]

Now, moving into the threading department. Utilizing Sleep(1) to "Lower CPU" in a multi-threaded application is nothing more then adding even more overhead on single processor systems, and can remove the reasoning for multiple processors to even be present. For anything more the Sleep(0), try utilizing OS Timer Objects. They exist for Win2k+ and Linux. They are more reliable, and achieve the lowered processor utilization, and they don't impart a cost comparativly speaking.

In .NET Thread.Sleep is another story (from what my .NET developers tell me). Since its managed, I would immagine that they are correct.

Implementing a threaded spin lock in Delphi requires you to perform a Sleep(0), at least in Delphi 7 and below, I can't speak to over Delphi 7. Simply put, this is due to Delphi not passing the processor lock's properly in assembly. Read up you can find it.