Get Performance Counter Instance Name (w3wp#XX) from ASP.NET worker process ID

让人想犯罪 __ 提交于 2019-11-30 11:45:00

The first hit on Google:

Multiple CLR performance counters appear that have names that resemble "W3wp#1"

When multiple ASP.NET worker processes are running, Common Language Runtime (CLR) performance counters will have names that resemble "W3wp#1" or "W3sp#2"and so on. This was remedied in .NET Framework 2.0 to include a counter named Process ID in the .NET CLR Memory performance object. This counter displays the process ID for an instance. You can use this counter to determine the CLR performance counter that is associated with a process.

Also KB 281884:

By default, Performance Monitor (Perfmon.msc) displays multiple processes that have the same name by enumerating the processes in the following way:

Process#1 Process#2 Process#3

Performance Monitor can also display these processes by appending the process ID (PID) to the name in the following way:

Process_PID

private static string GetProcessInstanceName(int pid)
{
  PerformanceCounterCategory cat = new PerformanceCounterCategory("Process");

  string[] instances = cat.GetInstanceNames();
  foreach (string instance in instances)
  {

     using (PerformanceCounter cnt = new PerformanceCounter("Process",  
          "ID Process", instance, true))
     {
        int val = (int) cnt.RawValue;
        if (val == pid)
        {
           return instance;
        }
     }
  }
  throw new Exception("Could not find performance counter " + 
      "instance name for current process. This is truly strange ...");
}

The example by chiru does not work in a specific case - when you have two versions of the same program, named the same, and one is not .net and you start the .net version after the non-.net version. The .Net version will be named applicaion#1 but when you access the CLR perf counters using this name, the instance names on the counter has the name withouth the #1, so you get failures.

Nick.

Even though changing of registry settings look quite easy, unfortunately most of us dont have the rights to do it on the server (or we dont want to touch it!). In that case, there is a small workaround. I have blogged about this here.

I know it has been answered before, but just for the sake of complete working code I'm posting this solution. Please note this code based on the method submitted by M4N in this chain:

public static long GetProcessPrivateWorkingSet64Size(int process_id)
{
  long process_size = 0;
  Process process = Process.GetProcessById(process_id);
  if (process == null) return process_size;
  string instanceName = GetProcessInstanceName(process.Id);
  var counter = new PerformanceCounter("Process", "Working Set - Private", instanceName, true);
  process_size = Convert.ToInt32(counter.NextValue()) / 1024;
  return process_size;
}

public static string GetProcessInstanceName(int process_id)
{
  PerformanceCounterCategory cat = new PerformanceCounterCategory("Process");
  string[] instances = cat.GetInstanceNames();
  foreach (string instance in instances)
  {
    using (PerformanceCounter cnt = new PerformanceCounter("Process", "ID Process", instance, true))
    {
       int val = (int)cnt.RawValue;
       if (val == process_id)
         return instance;
    }
  }
  throw new Exception("Could not find performance counter ");
}

Also, if you want to get the total memory of multiple instances of the same process use the above methods with the following one:

public static long GetPrivateWorkingSetForAllProcesses(string ProcessName)
{
  long totalMem = 0;
  Process[] process = Process.GetProcessesByName(ProcessName);
  foreach (Process proc in process)
  {
    long memsize = GetProcessPrivateWorkingSet64Size(proc.Id);
    totalMem += memsize;
  }
  return totalMem;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!