【问题标题】:C#: Accessing PerformanceCounters for the ".NET CLR Memory category"C#:访问“.NET CLR 内存类别”的 PerformanceCounters
【发布时间】:2011-06-09 23:51:08
【问题描述】:

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

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。

【问题讨论】:

  • 这仅仅是以管理员权限运行的情况,就像奥列格的回答一样?这为我解决了问题。

标签: c# .net memory performancecounter


【解决方案1】:

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

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

以管理员身份运行时

[Diagnostics.PerformanceCounterCategory]::Exists(".NET CLR 内存")

是的

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

[Diagnostics.PerformanceCounterCategory]::Exists(".NET CLR 内存")

错误

【讨论】:

  • +1 是的,最好将此标记为答案,以便更容易找到。一开始我忽略了它,因为它在底部。
  • 这是不正确的。拥有管理员权限就足够了,但您不需要需要管理员权限。请参阅stackoverflow.com/a/20174576/834521:将自己添加到组Performance Monitor Users,然后注销并登录。
【解决方案2】:

它应该工作。请注意,正如其他人已经设置的那样,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 进程(我们已经看到其实例名称)时,它可能不再存在(并且这样的实例也消失了)。

【讨论】:

  • 值得一提的是,原创文章由 Ingo Rammer 在archive.thinktecture.com/ingo/2004/06/…完成
  • @Che 谢谢。但是,请注意,确实是我自己提出了上述问题,对性能计数器等做了很多工作。给一个问题的适当解决方案,很多人提出“相同”的解决方案也就不足为奇了;-)
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-29
    相关资源
    最近更新 更多