Подтвердить что ты не робот

Может ли имя экземпляра счетчика производительности изменить процесс, даже если процесс не вышел

Я использую этот класс в качестве базового класса для категории тестов, которые запускают процесс и дают ему некоторый ввод, и ждут, пока он перестанет работать, прежде чем давать ему больше ввода.

public abstract class TestProcessLaunchingBase
{
    protected PerformanceCounter PerfCounter { get; set; }

    protected void WaitForProcessIdle()
    {
        while (true)
        {
            float oldValue = PerfCounter.NextValue();

            Thread.Sleep(1000);

            float nextValue = PerfCounter.NextValue();

            if (nextValue == 0)
                break;
        }
    }

    protected void FindSpawnedProcessPerfCounter(int processId)
    {
        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 == processId)
                {
                    PerfCounter = new PerformanceCounter("Process", "% Processor Time", instance);
                    break;
                }
            }

        }

        Assert.IsNotNull(PerfCounter, "Failed to perf counter");
    }
}

Эти тесты иногда терпят неудачу, потому что PerfCounter.NextValue() выдает

System.InvalidOperationException Экземпляр "foobar # 2" не существует в указанной категории

Кажется, что имя экземпляра счетчика производительности не является постоянным.

Если есть три процесса foobar, они могут иметь имена экземпляров

  • foobar pid 5331
  • foobar # 1 pid 5332
  • foobar # 2 pid 5333

Кажется, что если pid 5332 выходит из foobar # 2, становится foobar # 1.

Вопросы:

  • Является ли это документированным поведением? Можете ли вы не настойчивый счетчик производительности? Вам нужно каждый раз искать его?

  • В качестве альтернативы есть счетчик производительности, который может дать Время процессора для всех процессов с именем foobar

4b9b3361

Ответ 1

Я уже сталкивался с этой проблемой в прошлом. Шаблон ProcessName#InstanceNumber для имени экземпляра явно был плохим выбором для Microsoft, вы знаете, почему:)

Итак, у вас есть два варианта:

1) Создайте новый экземпляр PerformanceCounter каждый раз, используя ваш метод FindSpawnedProcessPerfCounter.

2) Чтобы изменить шаблон от ProcessName#InstanceNumber до ProcessName_ProcessID, выполните шаги, описанные в KB281884.

Проблема первого решения заключается в том, что для каждого нового экземпляра требуется некоторое время процессора.

Проблема второго решения заключается в том, что модификация реестра также влияет на все программы, которые также используют этот счетчик производительности. И это требует изменения реестра перед запуском приложения.

Последний вариант, который у вас есть, заключается в том, чтобы не использовать счетчики производительности вообще. Если вас интересует только информация ProcessorTime, есть некоторые функции Kernel32, которые вы могли бы вызвать, используя P/Invoke для ее получения.

EDIT:

Класс Process также предоставляет UserProcessorTime и PrivilegedProcessorTime (время процессора ядра). Оба возвращают экземпляр TimeSpan (= количество времени), поэтому, чтобы получить процент процессорного времени, вам придется выполнить некоторые вычисления самостоятельно (с использованием периода обновления и процессорного времени).

Ответ 2

Если вы должны использовать счетчики производительности, мой подход состоял бы в том, чтобы повторно создать счетчики производительности при возникновении исключения.

Когда генерируется исключение, удалите старые счетчики производительности, а затем создайте новые экземпляры счетчика производительности, используя идентификатор процесса для всех экземпляров вашего теста foobar. Здесь есть хорошая запись stackoverflow: Счетчик производительности по идентификатору процесса вместо имени?

Я предполагаю вашим выражением "запустить процесс и дать ему некоторый вклад", который вы держите за идентификатор процесса после его запуска. Таким образом, у вас всегда есть набор запущенных тестовых процессов, которые вы хотите контролировать.

С помощью этого метода вы получите только штраф за выполнение при ударе исключения.

Как уже указывалось @ken2k, вы можете изменить соглашение об именах счетчиков производительности для согласованности. По моему опыту, счетчики производительности могут иногда сталкиваться с любыми исключениями по ряду причин, по каким-то неожиданным причинам. Поэтому, даже если вы измените имя счетчика производительности, может быть неплохо иметь возможность повторно создать счетчики производительности, если это необходимо.