C#:访问“.NET CLR内存类别”的PerformanceCounters

时间:2011-01-16 13:51:59

标签: c# .net memory performancecounter

我正在尝试使用PerformanceCounter类访问位于".NET CLR Memory category"到C#的性能计数器。但是,无法使用我期望的正确类别/计数器名称来实例化类别

new PerformanceCounter(".NET CLR Memory", "# bytes in all heaps", Process.GetCurrentProcess().ProcessName);

我尝试使用以下代码循环遍历类别和计数器

string[] categories = PerformanceCounterCategory.GetCategories().Select(c => c.CategoryName).OrderBy(s => s).ToArray();
string toInspect = string.Join(",\r\n", categories);

System.Text.StringBuilder interestingToInspect = new System.Text.StringBuilder();
string[] interestingCategories = categories.Where(s => s.StartsWith(".NET") || s.Contains("Memory")).ToArray();
foreach (string interestingCategory in interestingCategories)
{
    PerformanceCounterCategory cat = new PerformanceCounterCategory(interestingCategory);
    foreach (PerformanceCounter counter in cat.GetCounters())
    {
        interestingToInspect.AppendLine(interestingCategory + ":" + counter.CounterName);
    }
}
toInspect = interestingToInspect.ToString();

但找不到任何似乎匹配的东西。是不可能从CLR中观察这些值,或者我做错了什么。

环境,如果重要,是在64位Windows 7机箱上运行的.NET 4.0。

3 个答案:

答案 0 :(得分:6)

您需要以管理员身份运行程序才能访问.NET CLR内存类别。

使用powershell尝试这个简单的测试:

以管理员身份运行时

  

[Diagnostics.PerformanceCounterCategory] ​​::存在(“。NET CLR Memory”)

     

在没有管理权限的情况下运行时:

  

[Diagnostics.PerformanceCounterCategory] ​​::存在(“。NET CLR Memory”)

     

答案 1 :(得分:3)

它应该工作。请注意,正如其他人已经设置的那样,CLR计数器是每个实例计数器,因此您需要为要查询计数器的进程指定实例名称。

因此,您在帖子顶部指定的声明应该有效。但是,您还应该使用构造函数重载,该重载允许您指定希望以“只读”模式访问实例:

new PerformanceCounter(".NET CLR Memory", "# bytes in all heaps", Process.GetCurrentProcess().ProcessName, true);

您发布的第二个代码片段不起作用,因为您没有为GetCounters()操作指定实例名称。请改用GetCounters(string instanceName)重载,它应该可以正常工作。

最后,请注意,实例名称不一定与Process.ProcessName(或Process.GetCurrentProcess().ProcessName相同)。如果有多个进程实例,即可执行,则通过附加#<number>来创建进程名称。要确定流程的实际实例名称,您应该查询.NET CLR Memory\Process ID计数器。

示例:

    public static string GetInstanceNameForProcessId(int pid)
    {
        var cat = new PerformanceCounterCategory(".NET CLR Memory");
        foreach (var instanceName in cat.GetInstanceNames())
        {
            try
            {
                 using (var pcPid = new PerformanceCounter(cat.CategoryName, "Process ID", instanceName))
                 {
                     if ((int)pcPid.NextValue() == pid)
                     {
                         return instanceName;
                     }
                 }
            }
            catch (InvalidOperationException)
            {
                // This may happen, if the PC-instance no longer exists between the
                // time we called GetInstanceNames() and the time we come around actually
                // try and use the instance. 
                // In this situation that is not an error, so ignore it.
            }
        }

        throw new ArgumentException(
            string.Format("No performance counter instance found for process id '{0}'", pid),
            "pid");
    }

通过此方法收集的实例名称也适用于其他“.NET CLR”类别中的性能计数器。

更新:在我们收集潜在实例名​​称和我们仔细阅读它们的时间之间添加了针对潜在竞争条件的缓解措施。当我们尝试使用它时,.NET进程(我们已经看到了一个实例名称)可能不再存在(并且这样的实例也已消失)。

答案 2 :(得分:1)

计数器是每个实例。尝试添加:

foreach (var instance in cat.GetInstanceNames())
{
    foreach (PerformanceCounter counter in cat.GetCounters(instance))
    {
        interestingToInspect.AppendLine(interestingCategory + ":" + counter.CounterName); 
    } 
}