Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SpinWait vs Sleep waiting. Which one to use?

Is it efficient to

SpinWait.SpinUntil(() => myPredicate(), 10000) 

for a timeout of 10000ms

or

Is it more efficient to use Thread.Sleep polling for the same condition For example something along the lines of the following SleepWait function:

public bool SleepWait(int timeOut) {     Stopwatch stopwatch = new Stopwatch();      stopwatch.Start();     while (!myPredicate() && stopwatch.ElapsedMilliseconds < timeOut)     {        Thread.Sleep(50)     }       return myPredicate() } 

I'm concerned that all the yielding of SpinWait may not be a good usage pattern if we are talking about timeouts over 1sec? Is this a valid assumption?

Which approach do you prefer and why? Is there another even better approach?


Update - Becoming more specific:

Is there a way to Make BlockingCollection Pulse a sleeping thread when it reaches bounded capacity? I rather avoid a busy waits alltogether as Marc Gravel suggests.

like image 761
Anastasiosyal Avatar asked Mar 15 '12 11:03

Anastasiosyal


People also ask

What is SpinWait?

SpinWait is a lightweight synchronization type that you can use in low-level scenarios to avoid the expensive context switches and kernel transitions that are required for kernel events.

What is thread SpinWait?

SpinWait essentially puts the processor into a very tight loop, with the loop count specified by the iterations parameter. The duration of the wait therefore depends on the speed of the processor.


1 Answers

In .NET 4 SpinWait performs CPU-intensive spinning for 10 iterations before yielding. But it does not return to the caller immediately after each of those cycles; instead, it calls Thread.SpinWait to spin via the CLR (essentially the OS) for a set time period. This time period is initially a few tens of nano-seconds but doubles with each iteration until the 10 iterations are complete. This enables clarity/predictability in the total time spent spinning (CPU-intensive) phase, which the system can tune according to conditions (number of cores etc.). If SpinWait remains in the spin-yielding phase for too long it will periodically sleep to allow other threads to proceed (see J. Albahari's blog for more information). This process is guaranteed to keep a core busy...

So, SpinWait limits the CPU-intensive spinning to a set number of iterations, after which it yields its time slice on every spin (by actually calling Thread.Yield and Thread.Sleep), lowering its resource consumption. It will also detect if the user is running a single core machine and yield on every cycle if that is the case.

With Thread.Sleep the thread is blocked. But this process will not be as expensive as the above in terms of CPU.

like image 174
MoonKnight Avatar answered Sep 19 '22 01:09

MoonKnight