C # SpinWait for Long Standby

This code consumes about zero CPU (i5 family)

public void SpinWait() { for (int i = 0; i < 10000; i++) { Task.Factory.StartNew(() => { var sw = new SpinWait(); while (true) { sw.SpinOnce(); } }); } } 

In my difference in code performance compared to SemaphoreSlim is 3 times or more for the case when the rotation is really justified (5 mops). However, I am concerned about its use for long-term expectations. The standard tip is to implement a two-phase wait operation. I could check the NextSpinWillYield property and enter a + reset counter to increase the default iterations without yielding, and then return to the semaphore.

But what are the disadvantages of using only SpinWait.SpinOnce for long-term wait? I looked at its implementation , and it correctly gives if necessary. It uses Thread.SpinWait , which on modern processors uses the PAUSE instruction and is quite efficient according to Intel .

One of the problems that I found when monitoring the task manager is the number of threads that gradually increase due to the ThreadPool algorithm by default (it adds a thread every second when all tasks are busy). This can be solved using ThreadPool.SetMaxThreads , and then the number of threads will be fixed, and CPU usage will still be around zero.

If the number of jobs with a long wait is limited, then what are the other problems using SpinWait.SpinOnce for a long wait. Does it depend on the processor family, OS, version of .NET?

(Just to clarify: I will still perform two-phase wait, I'm just curious, why not use SpinOnce all the time?)

+6
source share
1 answer

Well, the downside is exactly the one you see, your code takes a thread without doing anything. Preventing other code from running and forcing the thread manager to do something about it. Training with ThreadPool.SetMaxThreads () is just a tape help from what could be a very bleeding wound, but someday use it when you need to catch a plane home.

Spinning should only ever be undertaken if you have a very good guarantee that it is more efficient than a thread context switch. This means that you must be sure that the flow can continue within ~ 10,000 processor cycles or less. It's only 5 microseconds, give or take, allheckofalot less than most programmers consider "long-term."

Use a synchronization object that will instead invoke the context switch of the stream. Or the lock keyword.

Not only will this give the processor, so other waiting threads can do their job, thereby doing much more work, and are also great for the OS thread scheduler. The synchronization object that will be signaled will impede the priority of the thread, so it will most likely receive the next processor.

+9
source

All Articles