Still being a bit lazy about the blog -- I've been busy reading and working, both of which have longer quantums than writing for this blog, apparently.
Basically I just wanted to take a moment out of this Sunday afternoon to discuss thread quantums. This entire post is inspired by Windows Internals, 6th Ed. by Mark Russinovich, et al. As always, I could not recommend the book more highly.
So, we've all seen this screen, right? Adjust processor scheduling for best performance of "Programs" or "Background services:"
Well that seems like a very simple, straightforward choice... but who knows what it actually means? To answer that question, we need to know about a basic mechanism that Windows uses: Quantum.
A thread quantum is the amount of time that a thread is allowed to run until Windows checks if there is another thread at the same priority waiting for its chance to run. If there are no other threads of the same priority waiting to run, then the thread is allowed to run for another quantum.
Process Priority is that attribute that you can set on a process in Task Manager or in Process Explorer by right-clicking a process and choosing its priority. Even though it's the threads that actually "run" and not processes per se, each process can have many dynamically-lived threads, so Windows allows you to set a priority per process, and in turn each thread of that process inherits its base priority from its parent process. (Threads actually have two priority attributes, a base and a current priority. Scheduling decisions are made based on the thread's current priority.)
There are 32 process priority levels, 0-31, that are often given simplified labels such as "Normal," "Above Normal," "Real time," etc. Those are all within the subset of 0-1 on the Interrupt Request Level (IRQL) scale. What this means is that if you set a process to run at "Real Time" - or the highest possible priority - the process and its threads will still not have the ability to preempt or block hardware interrupts, but it could delay and even block the execution of important system threads, not to mention all other code running at Passive level. That is why you should have a very good reason for setting a process to such a high priority. Doing so has the ability to affect system-wide stability.
So now, back to quantum. We now know its definition, but how long exactly is a quantum? That depends on your hardware clock resolution, the speed of your processor, and how you have configured that setting pictured above to optimize performance for "Programs" or "Background services." As of Windows 7 and Windows Server 2008 R2, clients are configured to let threads run for 2 clock intervals before another scheduling decision is made, while it's 12 clock intervals on servers. So when you change that setting on the Performance Options page, you are bouncing back and forth between those two values. If you do some research, it would appear that these numbers have been tweaked in subsequent versions of Windows, which is why I pointed out "as of Win 7 and 2008 R2."
The reasoning for the longer default quantums on Server operating systems is to minimize context switching, and that if a process on a server is woken up, with a longer quantum it will have a better chance of completing the request and going back to sleep without being interrupted in between. On the other hand, shorter quantums can make things seem "snappier" on your desktop, leading to a better experience for desktop OSes.
As I said before, the resolution of your system clock is a factor in determining how long a quantum really is. There are a couple of different ways to obtain this number. One way is with clockres.exe from Sysinternals:
My current timer interval is 1ms. Programs running on your system can request system-wide changes to this timer, which is what has happened here. You can use powercfg.exe -energy to run a power efficiency analysis of your system that will identify processes that have made such requests to increase the resolution of the system timer. A system clock with a higher resolution causes the system to use more energy, which can be of significant concern on laptops and mobile devices that run on battery power. In my case, it's usually Chrome that asks that the system timer resolution be increased from its default of 15.6ms.
The other factor in determining the length of a quantum is processor frequency. You can obtain this value in several different ways, including using the !cpuinfo command in the debugger. I don't have a debugger handy on this machine, but I do already have Powershell open, so I'll just use that:
3.501GHz. This is a slightly overclocked Intel i5-2500k. Now that we have those two pieces of information, all that's left is some good old fashioned arithmetic:
The CPU completes 3,501,000,000 cycles per second, and the timer fires every 0.001 seconds. 3501000000 * 0.001 = 3501000 CPU cycles per clock interval.
1 Quantum Unit = 1/3 (one third) of a clock interval, therefore 1 Quantum Unit = 1167000 CPU cycles.
Assuming that at a rate of 3.501GHz, each CPU cycle is 286 picoseconds, that works out to 333.8 microseconds per quantum unit. Since my PC is configured for thread quantums of 2 clock intervals, and each clock interval is 3 quantum units, that means my PC is making a thread scheduling decision about every 2 milliseconds.
Now there's one final complication to this, and that is by using the "Programs" performance setting as opposed to the "Background services" setting, you are also enabling variable length quantums. Whereas a typically configured server will use fixed-length, 12 clock-interval quantums... but I'll leave off here and if you're interested in knowing more about variable length quantums, I would suggest the book I mentioned at the beginning of this post.