C #: Доступ к PerformanceCounters для «категории памяти .NET CLR» - PullRequest
9 голосов
/ 16 января 2011

Я пытаюсь получить доступ к счетчикам производительности, расположенным в ". NET CLR Memory Категория" через C #, используя класс PerformanceCounter. Однако a не может создать экземпляр категории с тем, что, как я ожидал, было бы правильным названием категории / счетчика

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 или я что-то делаю не так?

Среда, если это имеет значение, - это .NET 4.0, работающая на 64-битной Windows 7.

Ответы [ 3 ]

6 голосов
/ 11 декабря 2012

Вам необходимо запустить программу от имени администратора для доступа к категории .NET CLR Memory.

Попробуйте этот простой тест, используя powershell:

При работе от имени администратора

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

Правда

При работе без прав администратора:

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

Ложная

3 голосов
/ 17 января 2011

должно работать. Обратите внимание, что, как уже установили другие, счетчики 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 (для которого мы видели имя экземпляра) может больше не существовать (и такой экземпляр также исчез), когда мы пытаемся его использовать.

1 голос
/ 16 января 2011

Счетчики для каждого экземпляра.Попробуйте добавить:

foreach (var instance in cat.GetInstanceNames())
{
    foreach (PerformanceCounter counter in cat.GetCounters(instance))
    {
        interestingToInspect.AppendLine(interestingCategory + ":" + counter.CounterName); 
    } 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...