I <3 Steve McConnell*
Coding Horror
programming and human factors
by Jeff Atwood

August 10, 2005

Perfmon Gone Wild

When diagnosing server performance problems, the first tool I turn to is the humble Task Manager. That's usually enough to get a rough idea of where we are in the bottleneck shell game: is it CPU, Disk, Network or Memory?

But sometimes you need to dig into performance a little deeper. Then it's time to drag out Performance Monitor. I always resist doing this for as long as I can because using perfmon is like trying to sip from a fire hose: there are a zillion performance counters that produce veritable mountains of data. The .NET framework has probably a hundred .NET-specific performance counters, and that's just a tiny fraction of the available operating system performance counters. It's downright overwhelming. Where to begin?

Microsoft provides a helpful performance monitor wizard which walks you through the process of setting up a perfmon trace with default counters. Per the Wizard, that's the following:

\Cache\*
\Memory\*
\Network Interface(*)\*
\Objects\*
\Paging File(*)\*
\Physical Disk(*)\*
\Process(*)\*
\Processor(*)\*
\Redirector\*
\Server Work Queues(*)\*
\Server\*
\System\*

Once created, the trace can be stopped, started or modified via the Computer Management / System Tools / Performance Logs and Alerts / Counter Logs interface. Here's what the default wizard-produced trace looks like:

perfmon, or modern art?

It's perfmon gone wild!

This is way, way, WAY too much information. Let's see if we can narrow it down to some key performance counters:

  • Processor(_Total)\% Processor Time
    The percentage of elapsed time that the processor spends to execute a non-Idle thread. (more)
  • Processor(_Total)\Interrupts/sec
    An indirect indicator of the activity of hardware devices that generate interrupts, such as the system clock, the mouse, disk drivers, data communication lines, network interface cards, and other peripheral devices. (more)
  • System\Processor Queue Length
    The number of non-running ready threads in the processor queue. There is a single queue for processor time even on computers with multiple processors. If a computer has multiple processors, you need to divide this value by the number of processors servicing the workload. A sustained processor queue of less than 10 threads per processor is normally acceptable, depending on workload. (more)
  • Memory\Available Bytes
    The amount of physical memory, in bytes, available to processes running on the computer. Calculated by adding the amount of space on the Zeroed, Free, and Standby memory lists. (more)
  • Process(All_processes)\Working Set
    The set of recently touched memory pages for all processes. If free memory in the computer is above a threshold, pages are left in the Working Set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from Working Sets. If they are needed they will then be soft-faulted back into the Working Set before leaving main memory. (more)
  • Memory\Pages/sec
    The rate at which pages are read from or written to disk to resolve hard page faults. This is a primary indicator of the kinds of faults that cause system-wide delays. It includes pages retrieved to satisfy faults in the file system cache. (more)
  • PhysicalDisk\% Disk Time
    The percentage of elapsed time that the selected disk drive was busy servicing read or write requests. (more)
  • PhysicalDisk\Current Disk Queue Length
    The number of requests outstanding on the disk at the time the performance data is collected. Requests experience delays proportional to the length of this queue minus the number of spindles on the disks. For good performance, this difference should average less than two. (more)
  • Server\Bytes Received/sec
    The number of bytes the server has received from the network.
  • Server\Bytes Transmitted/sec
    The number of bytes the server has sent on the network.

Those counters should be enough to give you a general sense of whether you're dealing with a disk, memory, CPU, or network bottleneck-- without being too overwhelming.

If you need to capture more performance counters than this, I suggest switching the counter log to CSV output via the properties dialog. Then download Microsoft's excellent LogParser tool. Now you can slice, dice, and even graph the data however you like using a relatively simple SQL-like syntax.

Posted by Jeff Atwood    View blog reactions

 

« TryParse and the Exception Tax Passphrase Evangelism »

 

Comments

Thanks a lot for posting this! I'm in the process of testing an ASP.NET web app prior to deploying it onto a production server. It *does* seem like there's an awful lot of available counters...it'd be nice to select a few pre-defined counter groups with a single click. Thanks again!

zonker on August 12, 2005 11:25 AM

Great post title. Can't wait for the DVD.

David Grant on August 12, 2005 12:33 PM

Once you set up your counter settings [scale, color, line thickness, etc.,] I recommend saving the settings. You can do this by right-clicking on the gray charting area and clicking "Save As..." web page. Next time you start PerfMon, simply drag this html file into the gray charting area and you're ready to go. This will prevent the PerfMon gone wild scenerio above.

PerfMon rules!

I'm eager to take a look at Log Parser - I put together a similar application.

Eldar on August 22, 2005 05:08 PM

How do you submit a command from the logparser's(2.2) command-line tool that will sql-ize the possibly plural network-interface-card(s) in order to take the average (per nic card). Normally production servers have two nic cards. I have tried the following:
>logparser "SELECT AVG(\\SERVERNAME\NETWORK INTERFACE(INTEL ...)) FROM "
I am getting the following error,
Error: Syntax Error: : no matching closing parenthesis
PLEASE HELP!

dr43058 on August 10, 2007 01:20 PM







(hear it spoken)


(no HTML)




Content (c) 2008 Jeff Atwood. Logo image used with permission of the author. (c) 1993 Steven C. McConnell. All Rights Reserved.