Find a performance counter instance by a process ID

Performance Counters are a great feature of Windows which allow you to monitor applications and the whole system in a noninvasive manner. Which makes them even better is a fact that you can gather the performance data remotely. You can find some more information on using Performance Counters in my previous post: Diagnosing applications using Performance Counters. When diagnosing a faulting application I usually start with IO, Memory and CPU metrics available in the Process counter. The Process counter has a separate instance for each process that is running on your machine. By default, instance names are composed of the process name they represent and some identifier (in case there are multiple processes with the same name), eg. w3wp, w3wp#1, w3wp#2. As I’m mostly working with web applications hosted in IIS I often ran into problem which counter instance represents an application pool I want to monitor. So I wrote a simple Powershell script that will find the counter by process id:

function GetPidsFromPerfCounter([string]$ComputerName, [string]$pcounter, [int]$ProcessId, [string]$f) {
  # dump counter values
  typeperf -f CSV "$ComputerName$pcounter" -sc 1 -o $f -y | Out-Null
  # import and parse the CSV file
  $t = import-csv $f -Delimiter ","
  $t.psobject.Properties | select -skip 1 | ? { 
    if ($ProcessId -ge 0) { $_.value -eq $ProcessId } else { $true }
  } | % { "{1,6} => {0}" -f $_.Name,$_.Value } | Sort-Object

function Find-ProcessCounterByPid(
  [Parameter(Mandatory=$False,ValueFromPipeline=$True)][int]$ProcessId = -1,
  [Parameter(Mandatory=$False,ValueFromPipeline=$False)][string]$ComputerName = $null,
  [Parameter(Mandatory=$False,ValueFromPipeline=$False)][switch]$IncludeDotNet = $False
) {
  if (-not [String]::IsNullOrEmpty($ComputerName) -and -not $ComputerName.StartsWith("\\")) {
      $ComputerName = "\\" + $ComputerName
  $f = [System.IO.Path]::GetTempFileName()
  # native counters
  GetPidsFromPerfCounter $ComputerName "\Process(*)\ID Process" $ProcessId $f
  # for .net counters we need to grap CLR Memory\ID Process
  if ($IncludeDotNet) {
    Write-Host "  ------- .NET PIDs ---------"
    GetPidsFromPerfCounter $ComputerName "\.NET CLR Memory(*)\Process ID" $ProcessId $f
  del $f

You might now wonder why I haven’t used the Get-Counter cmdlet. Unfortunately there is some bug in it and it does not print counter instance indexes (the part coming after # in the instance name) which, in our case, is a core requirement. You can paste the above code into your Powershell module and make the GetPidsFromPerfCounter private. Then you can call Find-ProcessCounterByPid with no arguments – in which case the cmdlet will print all available counter instances:

PS Diagnostics> Find-ProcessCounterByPid
     0 => \\PECET\Process(_Total)\ID Process
     0 => \\PECET\Process(Idle)\ID Process
     4 => \\PECET\Process(System)\ID Process
   280 => \\PECET\Process(smss)\ID Process
   396 => \\PECET\Process(csrss)\ID Process
   404 => \\PECET\Process(svchost#5)\ID Process
   456 => \\PECET\Process(wininit)\ID Process
   464 => \\PECET\Process(csrss#1)\ID Process
   532 => \\PECET\Process(winlogon)\ID Process
   548 => \\PECET\Process(services)\ID Process
   572 => \\PECET\Process(lsass)\ID Process
   576 => \\PECET\Process(nvxdsync)\ID Process
   664 => \\PECET\Process(svchost)\ID Process
   700 => \\PECET\Process(nvvsvc)\ID Process
   724 => \\PECET\Process(nvSCPAPISvr)\ID Process
   752 => \\PECET\Process(nvvsvc#1)\ID Process
   768 => \\PECET\Process(svchost#1)\ID Process
   796 => \\PECET\Process(SkyDrive)\ID Process
   820 => \\PECET\Process(svchost#2)\ID Process
   860 => \\PECET\Process(dwm)\ID Process
   896 => \\PECET\Process(svchost#3)\ID Process
   912 => \\PECET\Process(chrome#11)\ID Process
   964 => \\PECET\Process(svchost#4)\ID Process
  1008 => \\PECET\Process(vpnui)\ID Process
  1148 => \\PECET\Process(vmware-authd)\ID Process
  1204 => \\PECET\Process(vpnagent)\ID Process
  1236 => \\PECET\Process(svchost#6)\ID Process
  1244 => \\PECET\Process(googledrivesync)\ID Process
  1384 => \\PECET\Process(spoolsv)\ID Process
  1420 => \\PECET\Process(svchost#7)\ID Process

or specify a concrete PID:

PS Diagnostics> Find-ProcessCounterByPid 768
   768 => \\PECET\Process(svchost#1)\ID Process

Additionally, if you are also interested in profiling .NET Applications, add -IncludeDotNet switch that will list .NET counters instance indexes, eg.:

PS Diagnostics> Find-ProcessCounterByPid -IncludeDotNet 5824
  5824 => \\PECET\Process(powershell)\ID Process
  ------- .NET PIDs ---------
  5824 => \\PECET\.NET CLR Memory(powershell)\Process ID

By adding -ComputerName switch you may also collect performance data from a remote machine. I hope you will find the script useful. If you have any ideas how to improve it drop me a comment 🙂

Introducing Musketeer – the performance counter data collector

In this post I will show you how to create a very simple Windows Service (I will call it Musketeer) that will collect information about other processes running on a server. Such a tool might be helpful if you host Windows services on some remote server and you want to store information about their performance in a database for further analysis. This tool might also be a cure if your admins didn’t give you enough privileges to connect the Performance Monitor to the remote server:)

Continue reading

Diagnosing applications using Performance Counters

Performance diagnosis is a very important aspect of a software creation process. Higher and higher requirements for application responsiveness and speed should encourage us to start collecting performance metrics even during the application development phase. Fortunately in Windows we have a big number of sources that we can query in order to retrieve the performance and trace logs, including: Event Tracing for Windows (ETW), Event Logging and Performance Counters. Today I would like to write about the last item of this list. Performance counters are used to provide information how well the operating system or an application, service, or driver is performing. Therefore they can often help you determine system bottlenecks or application performance problems. I split the post in four parts: the first part is a general description of performance counters architecture, in the second part you can read how to collect data provided by the counters, in the third how to filter and organize it and finally, in the forth part, how to display and analyze it.
Continue reading