I would like to display some memory statistics (working set, GCs etc.) on a web page using the .NET/Process performance counters. Unfortunately, if there are multiple application pools on that server, they are differentiated using an index (#1, #2 etc.) but I don’t know how to match a process ID (which I have) to that #xx index. Is there a programmatic way (from an ASP.NET web page)?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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 ...");
}
Method 2
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
Method 3
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.
Method 4
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.
Method 5
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;
}
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0