In the Internet server world, Web managers need to know how to achieve the best possible performance with the hardware and software at their disposal. This task is often more difficult than most managers expect and requires a great deal of testing and research. Let's dive beneath the surface of this vast and confusing subject so you can formulate a plan for optimizing your Web site.

Determining a Performance Baseline
Before you start testing and tuning servers, you need to determine a reasonable performance baseline for your Web site. You need to consider the type of content you serve and the service level customers expect. For example, a customer who clicks a link to get a local newspaper article expects the page to appear faster than does a customer who requests a copy of his or her bank transactions for the past 60 days. In the latter case, a customer might expect to wait 10 to 15 seconds for the response, whereas the customer trying to connect to the newspaper article might become frustrated after 7 seconds. Keep in mind that different areas of the site might require different baselines. This fact is especially important for servers that host multiple sites.

After you determine a site's performance baseline, you might need to break down the site's functionality into categories so that you can measure each part accurately. For example, if your Web server returns data from a back-end Microsoft SQL Server and takes 10 seconds to serve a page, you'll need to determine whether the Web server or the SQL Server is causing the bulk of the delay. Although you'll likely be able to achieve performance gains from both the Web server and SQL Server, knowing which server is causing the largest share of the delay will tell you which server offers the greatest potential for overall performance improvement.

Stress Testing
Next, you'll gather the Web site's performance data. In some cases, you'll stress-test a site before you put it into production; in others, you'll directly monitor production servers. When you stress-test a site, create the most realistic environment possible. Too often, I see companies stress-test with positive results, only to have the server fail as soon as it goes live because the test environment didn't represent a real-world situation. Make sure test client machines have adequate power—if clients are underpowered, they can't push the servers to the limit in a stress test.

Microsoft and several third-party vendors offer simulation tools you can use to stress-test your servers. Microsoft offers the Web Capacity Analysis Tool (WCAT) and the Web Application Stress (WAS) tool, which the company recently enhanced and repackaged as Visual Studio .NET's Application Center Test tool. The Microsoft Application Center Test tool provides comparative performance-run analyses. For information about this tool, visit http://webtool.rte.microsoft.com. The WCAT and WAS tool ship on the Microsoft Windows 2000 Server Resource Kit CD-ROM, along with documentation for using them. Be sure to consider a wide range of test scenarios as you create the test scripts.

Monitoring Web Site Performance
When you're ready to test your server, and when your server is in production, you'll need to monitor its performance. For more information about performance-testing your systems, see "Performance-Troubleshooting Resources." The most widely used monitoring tool is Performance Monitor, which is built in to all Windows NT—based OSs. This article assumes you know how to use Performance Monitor and discusses how to interpret Performance Monitor's results. If you're unfamiliar with this tool, read the Microsoft article "HOW TO: Manage Performance Monitor Counters in Windows 2000 (http://support.microsoft.com/?kbid=302521) for an overview.

To determine which parts of your system you need to tune, you'll need to monitor several functional areas of IIS and NT, including memory, processor, hard disk, and network performance, and various software functions on the Web site, such as Active Server Pages (ASP) processing time, IIS caching, and back-end processing times. The following list outlines a few of the Performance Monitor counters you can use.

  • Memory: Available Bytes—This counter measures the memory available to run applications. You don't want this value to fall below 5 to 10 percent of the total computer memory.
  • Process: Working Set: Inetinfo—This counter measures the amount of memory (including paged memory) that Inetinfo is using. This amount includes the cache memory and connection memory.
  • Memory: Page Faults/sec: Inetinfo—This counter measures the rate (page faults/sec) at which requested memory isn't at the specified location. This counter includes times when the system has to go to the swap file to retrieve memory. After you determine an average Inetinfo Working Set size for your server's load, see whether you can lower the Page Faults by adding more RAM, thus keeping more of the Working Set in memory.
  • Internet Information Services Global: File Cache Hits %—This counter measures the ratio of successful retrievals from cache (for static content) versus the number of requests made to the cache. A value of 80 to 90 percent for a static heavy site is considered good.
  • Internet Information Services Global: File Cache Flushes—This counter measures the number of times an item is flushed from the cache. Keep in mind that IIS can flush items from the cache because of a timeout or because the content changes.
  • Internet Information Services Global: File Cache Hits—This counter measures the number of times that items are retrieved from the cache. Compare this number with the File Cache Flushes figure. If your flushes are more than 50 percent of the number of hits, you might need to increase the cache size. If your flushes are less than 15 percent of the number of hits, you might be wasting memory.
  • Processor: % Processor Time—This counter measures the percentage of time that the processor is working versus being idle. A sustained value of more than 80 percent can indicate a processor bottleneck.
  • Thread: Context Switches/sec—This counter measures the number of context switches per second. A context switch occurs when one thread stops executing on the processor and another thread starts. On an idle processor, you might see as many as 800 to 1000 context switches per second, and on a busy machine, the count can increase to a few thousand. If a busy machine shows more than five times the number of switches than when the processor is idle, you might be seeing a bottleneck.
  • Active Server Pages: Requests/sec—This counter measures the number of ASP requests coming in to IIS. This counter doesn't include static requests or requests for other dynamic data.
  • Active Server Pages: Requests Executing—This counter measures the number of ASP requests being processed in the ASP thread pool.
  • Active Server Pages: Request Wait Time—This counter measures the amount of time (in milliseconds) that the most recent request waited in the request queue.
  • Active Server Pages: Request Execution Time—This counter measures the amount of time (in milliseconds) that the most recent request took to process.
  • Active Server Pages: Requests Queued—This counter measures the number of requests currently waiting in the ASP queue.

Using the Results
Using performance data to diagnose a software problem is an important engineering skill and a prerequisite for determining how to fix performance problems (e.g., making code changes, changing server settings). For an in-depth discussion of troubleshooting performance problems, see "Troubleshooting High CPU Utilization" (February 2002, http://www.windowswebsolutions.com, InstantDoc ID 23574). I concentrate here on some of the server settings you can change. Be sure to test any changes to ensure that they don't decrease your production system's performance.

IIS metabase settings. You can tune your Web servers by adjusting the following performance settings in the metabase. (Note that this is only a partial list of values that you can set.)

  • AspThreadGateEnabled (not available in IIS 4.0 and earlier)—This setting, if enabled, turns on the ASP thread gate, which dynamically monitors and modifies the number of worker threads that each dllhost.exe uses to handle incoming ASP requests. The feature compares CPU usage with set thresholds (AspThreadGateLoadLow and AspThreadGateLoadHigh) and adjusts the number of threads that the system permits to execute. Modify this setting if you notice that your server is queuing ASP requests or that ASP requests are causing CPU usage greater than 80 percent.
  • AspProcessorThreadMax (ProcessorThreadMax in IIS 4.0)—This setting limits the number of worker threads that IIS will allow for ASP request handling. This number is different for each process, so each process has an ASP worker thread pool. The default value is 25 threads per processor. Although ASP thread-gating functionality uses this setting, thread gating doesn't need to be enabled for the setting to work. One situation in which you might want to use this setting without thread gating enabled is if you notice a lot of backed-up requests and you know that none of the requests use CPU power (e.g., they're on a back-end database).
  • AspScriptEngineCacheMax—This value sets the number of ASP script engines to cache in memory. ASP script engines turn a parsed script into byte code. In IIS 5.0, the default value is 125. In IIS 4.0, the default value is 30. If your site has thousands of ASP pages, you can probably improve performance by increasing the default value.
  • AspScriptFileCacheSize—This setting adjusts the number of parsed ASP scripts to keep in memory. The default value is 250. If you set this value to 0, no scripts are cached; if you set it to -1, all scripts are cached.
  • ConnectionTimeout—This setting lets you set the amount of time before IIS terminates an inactive connection. The default value is 900 seconds (15 minutes). If you habitually run out of connections on the server, try decreasing this value. If your site has a page that takes a long time to return and you don't have a lot of traffic on the server, you can increase this number. Be sure that you don't increase this value to the point that your server runs out of connections when it reaches peak load.
  • MaxEndpointConnections—This value sets the maximum number of listeners that will be available on any given network endpoint (e.g., port 80). The default value is 100. If clients often get a Server Too Busy error on a heavily used site but they can connect successfully after only one or two refreshes, you might need to increase this number (along with the ServerListenBacklog value).
  • ServerListenBacklog—This setting adjusts the number of outstanding sockets that your Web server can queue. The default value is based on the ServerSize setting. If ServerSize is set to 0, the default number of sockets is 5; if ServerSize is 1, the default number is 40; and if ServerSize is 2, the default number is 100. The lesser of the ServerListenBacklog value and MaxEndpointConnections value is used to determine how many connections are pooled on your server.
  • ServerSize—This setting shows the approximate number of requests per day you expect to receive. A value of 0 indicates fewer than 10,000 requests per day; 1 indicates fewer than 100,000 per day; and 2 indicates more than 100,000 per day. You can set this value in the Internet Service Manager (ISM) console's Performance Tuning slider.

Registry settings. The following registry settings can affect your site's performance. Navigate to the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\InetInfo\Parameters subkey and check the following values:

  • MaxPoolThreads—This value indicates the maximum number of threads created to handle incoming static requests. The default value is four per processor. If your cache settings are adequate for your Web traffic, you shouldn't need to tweak this value.
  • PoolThreadLimit—This value overrides the MaxPoolThreads value for requests to ISAPI Extensions and to other services in Inetinfo (e.g., FTP, SMTP). The default value is two times the number of megabytes of RAM in the system (with a maximum default value of 256). Because threads in the IIS thread pool exist for only 24 hours, you usually don't need to change this number unless you see a great deal of context switching, in which case you might want to decrease this setting.

Know Your Systems
Keep in mind that careful observation and testing of your Web server systems, as well as a basic understanding of what's happening on these systems, are key to optimizing performance. If your system is running slowly, determine the reason before you start changing settings, or you might make the system slower. If you use common sense and good troubleshooting techniques, you'll be able to keep your systems finely tuned.

Performance-Troubleshooting Resources
MICROSOFT DEVELOPER NETWORK
(MSDN) LIBRARY ARTICLES
"Collecting Performance Data"
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnduwon/html/d5collection.asp

"25+ ASP Tips to Improve Performance and Style"
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnasp/html/asptips.asp

"Understanding Performance Testing"
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnduwon/html/d5dplyover.asp

MICROSOFT TECHNET ARTICLE
"The Art and Science of Web Server Tuning with Internet Information Services 5.0"
http://www.microsoft.com/technet/treeview/default.asp?url=/technet/prodtechnol/iis/maintain/optimize/iis5tune.asp