Microsoft stretches quantums to balance performance

In the February issue, Trip Stiles passed along a rumor that unlike Windows NT Workstation 3.51, NT Workstation 4.0's responsiveness can appear to diminish when you run several concurrent tasks. The rumor pinned this behavior on NT 4.0's inability to adjust the process priority independently of the priority you assign to an application. Our alert readers quickly pointed out that NT Workstation 4.0 uses a different method from NT Workstation 3.51 to optimize applications.In light of this revelation, I'd like to explain how NT Workstation 4.0 dispenses CPU time to foreground applications. Let's see how NT Workstation 4.0 schedules applications to run, how priority and CPU quantums fit into NT's process priority model, and what this approach means for foreground applications running in either NT Workstation or NT Server.

Processes and Threads 101
NT views applications in terms of processes and threads. A process consists of an address space, a set of resources, and a set of threads that run in context of the process. Threads are the parts of an application that execute, and applications can have multiple threads. Each process has memory space separate from that of other processes, but all threads belonging to a process share the same set of resources.

NT assigns a priority to all processes and threads. Processes fall into one of four priority classes: realtime, high, normal, and idle. NT assigns each thread, which the application creates as one of the final steps of process creation, to 1 of 31 priority levels based on the thread's process priority. (Although the priority levels are numbered from 0 to 31, NT does not use the level 0 for priority user threads.) This priority might not be the same for all threads within a process. You can view the priority of a process and its threads with the Microsoft Windows NT Server 4.0 Resource Kit Process Viewer tool, which you see in Screen 1.

Process Viewer divides process priority into three categories (Very High, Normal, Idle), as you see in the Priority section in the middle right of the dialog box in Screen 1. More important to this discussion is the thread Dynamic Priority setting, which you see in the Thread Information section at the bottom of the dialog box. All threads have two priorities: a starting priority and a current (dynamic) priority.

NT allocates CPU time to applications by individual threads within that application's process, making that allocation according to individual thread priority (the higher the priority level number, the greater the thread priority). NT runs threads with the highest priority first. If more than one thread with the same priority is ready to run at the same time, NT divides CPU time among those threads in timeslice or quantum units.

The length of a quantum depends on the system architecture (e.g., Intel systems have a different timeslice from Alpha systems) and the version of NT. For example, an NT Server-based quantum is three times as long as the NT Workstation quantum on a given architecture. Microsoft made the quantums' lengths different to accommodate the intended use of each platform: NT Workstation's shorter quantum works better for a single user who's switching between applications, and NT Server performs better while providing services and data to an entire network. Microsoft designed NT so that the CPU is idle as often as possible and designed the length of the quantum to give each version of the operating system a chance to finish one operation and begin another.

The Mechanics of Scheduling Threads in NT
NT is a priority-based, preemptive, multitasking operating system (i.e., it allocates CPU time in quantum units and dispenses these quantums to threads according to each thread's priority). A thread can get CPU time in three ways:

  • The thread that's running relinquishes the processor because it finishes its quantum
  • The thread that's running relinquishes the processor because it's waiting for another event to take place
  • A thread that was waiting for an event to take place becomes ready, or a thread with a higher priority than a thread that's running becomes ready to run and preempts the running thread and interrupts its quantum

Let's look at each of these scenarios. The first situation is easy to grasp: The highest-priority threads take turns using the CPU. When one thread completes its quantum, it moves to the back of the queue and awaits its next turn at the CPU (or if it's finished with its task, it terminates). This orderly process is similar to how a lunch line at a fast-food restaurant would work in a perfect world.

But what happens if a thread isn't satisfied with a hamburger from the warming bin and orders something that takes extra time to prepare? In this situation, rather than hold up the line, the waiting thread steps aside and lets the next thread in the queue place its order and get its lunch. The second thread doesn't preempt the first thread, but because the first thread is waiting for an event to take place (i.e., it's in a wait state), it relinquishes control of the processor, and the second thread is free to execute.

What happens when the first thread's special order is ready? At that point, assuming the thread that's running doesn't have a higher priority than the thread that was in the wait state, the waiting thread preempts the thread that was running. The waiting thread doesn't restart its transaction with the cashier (CPU); it just finishes the existing transaction.

Finally, if a thread with a higher priority than a thread that's running is ready to execute, it can preempt the running thread. For example, imagine that Joe Thread is standing in line at that fast-food restaurant and the President of the United States Thread walks in. The fact that Joe Thread was already running doesn't matter because President Thread has a higher priority. When President Thread receives its order, Joe Thread is free to continue its cycle.

Foreground and Background Performance
So how do threads and quantums relate to program performance? The answer depends on the version of NT you're running. Both NT 3.5x and NT 4.0 let you give foreground applications more CPU time than background applications (NT assumes that you're most concerned with your foreground applications if you're using the desktop product), but each operating system takes a different approach. NT 3.5x Workstation increases the priority of threads running in the foreground so that they can bump other threads waiting for CPU time. In contrast, NT 4.0 Workstation increases the number of quantums that a foreground thread receives--by default, threads belonging to background applications get one quantum, and threads belonging to foreground applications get three quantums. The threads don't change priority, but when competing with other threads of the same priority, they get to run a little longer than the average.

This change in design between NT 3.5x and NT 4.0 means that foreground applications might not run as well under NT Workstation 4.0 as they did under NT Workstation 3.5x. Microsoft made the change to improve background application performance, which can suffer when foreground applications hog the CPU.

You can adjust your system settings so that foreground and background applications are more balanced in NT Workstation 4.0: Open the System applet in the Control Panel and click the Performance tab, as you see in Screen 2. For both NT Server 4.0 and NT Workstation 4.0, the default setting, which you see in the Application Performance section of the dialog box in Screen 2, is three quantums for foreground applications. You can move the slider to the center of the bar and reduce the quantum setting to two. Although NT Server has this control, by doing some research on the NT scheduling code, I found that adjusting this setting doesn't affect the priority of a foreground application--NT Server threads always run at the same long quantum. Strange, but true. The reason this setting doesn't affect NT Server may be related to the fact that this operating system is a server platform. Therefore, NT Server might assume that all applications (not just those in the foreground) need the original percentages of CPU time.

If you're interested in finding this setting in the NT Workstation Registry, go to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\PriorityControl\Win32PrioritySeparation. The default value of this DWORD string is 0*2. As you can see, even though thread priority is no longer increased for foreground apps, NT Workstation 4.0 includes provisions for increasing their responsiveness. Quantum stretching is not something you can easily see, like changing the priority, but it's there.