我想使用 .NET/Process 性能计数器在网页上显示一些内存统计信息(工作集、GC 等)。不幸的是,如果该服务器上有多个应用程序池,它们会使用索引(#1、#2 等)进行区分,但我不知道如何将进程 ID(我拥有)与该 #xx 索引匹配。是否有编程方式(来自 ASP.NET 网页)?
5 回答
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 ...");
}
谷歌上的第一击:
当多个 ASP.NET 工作进程正在运行时,公共语言运行时 (CLR) 性能计数器的名称将类似于“W3wp#1”或“W3sp#2”等。这在 .NET Framework 2.0 中得到了纠正,在 .NET CLR 内存性能对象中包含一个名为 Process ID 的计数器。此计数器显示实例的进程 ID。您可以使用此计数器来确定与进程关联的 CLR 性能计数器。
还有知识库 281884:
默认情况下,性能监视器 (Perfmon.msc) 通过按以下方式枚举进程来显示具有相同名称的多个进程:
进程#1 进程#2 进程#3
性能监视器还可以通过以下方式将进程 ID (PID) 附加到名称中来显示这些进程:
进程_PID
尽管更改注册表设置看起来很容易,但不幸的是,我们大多数人都无权在服务器上进行更改(或者我们不想碰它!)。在这种情况下,有一个小的解决方法。我在这里写过关于这个的博客。
chiru 的示例在特定情况下不起作用 - 当您有同一个程序的两个版本,名称相同,一个不是 .net 并且您在非 .net 版本之后启动 .net 版本。.Net 版本将命名为 applicaion#1,但是当您使用此名称访问 CLR 性能计数器时,计数器上的实例名称的名称没有 #1,因此您会失败。
缺口。
我知道之前已经回答过了,但只是为了完整的工作代码,我发布了这个解决方案。请注意此代码基于 M4N 在此链中提交的方法:
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 ");
}
此外,如果要获取同一进程的多个实例的总内存,请使用上述方法和以下方法:
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;
}