Unleash The Beast!

Turn this script loose and see how easy it is to maximize processor performance across multiple workstations!


I just got a new laptop at work. My "old" one—a Pentium II 300 MHz—was considered a "Desktop Replacement" notebook when I got it three years ago. If that's true, then this one must be considered a "Crazy Supercomputer Replacement"—a Pentium III 1.13 GHz, with 512MB RAM, built-in wireless, LAN and modem. As Tim "The Tool Man" Taylor would say, "Arr, Arr, ARR!!" I was in heaven!

Until the newness wore off, which took about 15 minutes.

Then I was back to tapping my fingers on my desk waiting for applications to start. Yes, it's true: Computers will simply never be fast enough to satisfy us. All isn't lost, though. There are things we can do to maximize their performance. The featured script this month is one I wrote back in my NT 4.0 days to configure processor performance on servers. Over the years, it's evolved to be the first script I run on a new workstation (or one that I've just rebuilt). Let's take a look at it first, then I'll explain what it does and why it's so useful.

<?xml version="1.0" ?>
<package>
   <comment>
   ChangeFGPerf.wsf
   This script updates the Win32PrioritySeparation
   key in the registry to boost the performance
   of applications running in the foreground
   </comment>

<job>
   <runtime>
      <description>

      This script allows you to change the performance role of your computer
      </description>

      <example>
      C:\CScript ChangeFGPerf.wsf /Role:[W/S]
      </example>

     <named
        name=
"Role"
        helpstring="The role (server or workstation) for the computer"
        type="string"
        required="true"
       />
     </runtime>
     <object id=
"objShell" progid="WScript.Shell"/>

     <script language="VBScript">
     <![CDATA[
        'Change foreground performance
        Option Explicit

        Dim strRole, strKey, strDataType
        strKey="HKLM\System\CurrentControlSet\Control\
                     PriorityControl\Win32PrioritySeparation"
        strDataType="REG_DWORD"
        strRole=UCase(WScript.Arguments.Named.Item("Role"))

        Select Case strRole
           Case "W"
           objShell.RegWrite strKey, 38, strDataType
           WScript.Echo "Priority Control has been set to optimize foreground applications."
           WScript.Quit

           Case "S"
           objShell.RegWrite strKey, 24, strDataType
           WScript.Echo "Priority Control has been set to optimize background services."
           WScript.Quit

        End Select
        WScript.Arguments.ShowUsage()
        WScript.Quit

     ]]>
     </script>
   </job>
</package>

Splitting Threads
What this script does is simple enough: It changes the registry setting "Win32PrioritySeparation." This setting controls the priority of foreground processes—sort of. What it actually does is determine how much processor time the threads of a process receive and the relative priority of foreground and background processes. Of course, there's a GUI tool for this that I'm sure you've used many times: the System Applet. Priority control is set by selecting the Advanced tab and clicking the Settings button under Performance. This opens the Performance Options window. Select the Advanced tab and make your selection under Processor Scheduling (see Figure 1).

Boosting foreground apps with scripts
Figure 1. This machine is set to boost foreground applications—or is it?

You have two choices: Adjust for Programs or Adjust for Background Services. Pretty straightforward, yes? So why bother with a script? Well, the script allows you to automate these Workstation or Server "role" settings. You specify the role using the command-line argument /Role: . A "W" ("W"orkstations) changes the value to "boost" foreground processes. "S" ("S"erver) changes the setting for background processes.

Role Reversal
Depending upon a computer's usage in your organization, you may want to modify how it handles processes rather than simply rely on the default settings. For instance, if you work for a small company and use IIS on Windows 2000/XP Professional to run your intranet, you'd certainly want to maximize background processes on this machine. This script should be on your checklist to be applied every time you change the primary function of a computer.

But Wait, There's More
Using a script to directly edit these values provides even more benefit than simply specifying one of two possible computer roles. A lot more! Let's explore this by looking at what these settings meant back in the "old days" of NT 4.0. If you use the System Applet to look at these same settings on a Windows NT 4.0 computer, you'll notice a slider instead of the two radio buttons. There are three choices on the "Select Performance Boost for Foreground Applications" slider: None, "Balanced", and Maximum. The corresponding registry setting would be either 0 (None), 1 (Balanced), or 2 (Maximum). In Windows 2000, the usage of this key has changed. In NT 4.0, this key merely affected thread priority. In Windows 2000 (and XP/2002 Server, as well), it allows you to control not only relative priority for processes, but also the length of the intervals (i.e. how long each process runs once it is scheduled), and whether or not these intervals are fixed-length or variable-length. This is possible because with Win2K, this registry setting, rather than being a "real" value of 0, 1, or 2, is now a 6-bit bitmask value—comprised as three 2-bit pairs—with each pair specifying a particular element of thread priority control.

Now, here's the good part: Microsoft managed to preserve the NT 4.0 settings, so that they would have the same effect if applied to the bitmask of a Win2000/XP machine. In fact, the "old" values are still the default settings for this key! See for yourself and open the System Applet. If you have Win2000/XP Professional installed, it should already be set to Adjust for Programs. Now open the registry and browse to HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\PriorityControl. (This is where we include the "standard" disclaimer that directly editing the registry—or even looking at it with Regedit.exe—may permanently damage your computer. Other side-effects include male pattern baldness, dry mouth, itchy scalp, recurring migraine headaches, and/or death.) Unless you've changed this previously, the value for Win32PrioritySeparation will be 2 (the old NT 4.0 setting). Now, switch back to the "Performance Options" window, tick the "Adjust for Background Services" option and click Apply. Switch back to the registry editor and hit F5 to refresh it. Now it's 24. This value of 24 has the same effect on processor scheduling as the NT 4.0 value of 0. Now use the GUI to switch it back to "Adjust for Programs" and click Apply. Back to regedit, F5 to refresh, and...tada! It's 38, which has the same effect as the NT 4.0 value of 2.

Advanced Priority Control

The Win32PrioritySeparation value for Windows 2000/XP takes on a whole new dynamic from its previous incarnation in Windows NT 4.0 and earlier. As mentioned in the column, the new setting gives you control over not only process priority, but also the amount of processor time allocated to the threads of a process and whether or not the length of time is fixed or variable.

A Review of Binary Math
We've dealt with bitmasks before (see "A Bit About Binary Math" in my December 2000 column); please feel free to refer back to it if you need a little refresher. Go ahead… I'll wait. OK, you're back! Now that you've been reminded that it's not the number, but the bits that are important, let's move on to how we use this bitmask for priority control.

So… How's This Work?
The bitmask is divided into three, two-bit pairs (AABBCC). Each bit-pair corresponds to certain behavior. I've broken it down below:

The highest bits (AABBCC) specify whether the processor interval (the amount of time allocated to the threads of a process) is relatively short or long. The "middle" bits (AABBCC) specify whether the interval is fixed or variable. The lowest bits (AABBCC) determine the ratio of foreground threads to background threads. Certain values cause different behavior, depending on whether you are using Professional or Server. Here's a table that breaks down each bit-pair.

Value Meaning
Highest Bits Interval
00 or 11 Shorter Intervals (Windows 2000/XP Professional); Longer Intervals (Windows 2000/2002 Server)
01 Longer Intervals
10 Shorter Intervals
Middle Bits Fixed or variable
00 or 11 Variable length (Pro); Fixed length (Server)
01 Variable Length
10 Fixed Length
Lowest Bits Ratio of foreground to background threads
00 Equal and fixed. This value also overrides the Fixed/Variable value to Fixed.
01 2:1. Foreground processes receive twice the processor time of background processes.
10 or 11 3:1. Foreground processes receive three times the processor time of background processes.

Now let's apply the "standard" and "default" values of the System Applet and see what this translates to.

  • Adjust for Programs—The default value is 2 (000010 binary). The "standard" value (set when changed using the System Applet) is 38 (100110 binary). Notice that with Win2000 Pro, these values have the same effect - shorter intervals, variable length, 3:1 ratio.
  • Adjust for Background Services—The default value is 0. The "standard" value is 24 (011000 binary) Notice that regardless of whether you are running Server or Professional, the values have the same effect - longer intervals, fixed length, equal ratio.

Putting it into Action
Remember that default thread settings are designed to be generic and may not be optimal for your system depending upon the services and applications you are running. By combining different bit-pair values, you can tweak thread processing significantly, rather than simply "living with" the default behavior. I encourage you to experiment with different settings to find what works best on your system.

Changing Workstation Roles, and Then Some
While this script is valuable as a means of changing how a particular machine handles foreground and background processes, its real value lies in its ability to perform low-level tweaking of thread performance, which I explain in "Advanced Priority Control" above.

Featured