Именование счетчиков производительности нескольких экземпляров в .NET.

Большинство счетчиков производительности нескольких экземпляров в Windows кажутся автоматически (?) на #n на конце, если имеется более одного экземпляра с тем же именем.

Например: если в Perfmon вы просматриваете категорию Process, вы увидите:

...
dwm
explorer
explorer#1
...

У меня есть два процесса explorer.exe, поэтому второй счетчик добавляет # 1 к его имени.

Когда я пытаюсь сделать это в приложении .NET:

  • Я могу создать категорию и зарегистрировать экземпляр (используя PerformanceCounterCategory.Create, который принимает CounterCreationDataCollection).
  • Я могу открыть счетчик для записи и записи на него.

Когда я открываю счетчик второй раз (в другом процессе), он открывает тот же счетчик. Это означает, что у меня есть два процесса, сражающихся за счетчики.

Документация для PerformanceCounter.InstanceName утверждает, что # не разрешено в имени.

Итак: как у меня есть счетчики производительности нескольких экземпляров, которые на самом деле являются несколькими экземплярами? А где второй (и последующий) экземпляр получает #n к имени?

То есть: я знаю, что я могу поместить идентификатор процесса (например,) в имя экземпляра. Это работает, но имеет неприятный побочный эффект, что перезапуск процесса приводит к новому PID, и Perfmon продолжает отслеживать старый счетчик.

Update:

Я создаю категорию (и счетчик) следующим образом:

const string categoryName = "Test App";
const string counterName = "Number of kittens";
string instanceName =
    Path.GetFileNameWithoutExtension(
        Process.GetCurrentProcess().MainModule.FileName);

if (!PerformanceCounterCategory.Exists(categoryName))
{
    var counterCreationDataCollection = new CounterCreationDataCollection
        {
            new CounterCreationData(counterName, "",
                PerformanceCounterType.NumberOfItems32)
        };

    PerformanceCounterCategory.Create(categoryName, "",
        PerformanceCounterCategoryType.MultiInstance,
        counterCreationDataCollection);
}

Я открываю счетчик следующим образом:

PerformanceCounter counter = new PerformanceCounter(
        categoryName, counterName, instanceName, readOnly: false);

Ответ 1

Я думаю, что ваша проблема связана с тем, что .NET более свободен в отношении счетчиков производительности и фактически обходит API WinForm PerfLib.

При использовании собственного API PerfLib вы регистрируете категории во время настройки - и создаете экземпляры из процесса с помощью дескрипторов. Так что с native API нет простого способа поделиться экземпляром счетчика. Поэтому, когда два экземпляра счетчика обращаются с тем же именем, они фактически имеют разные дескрипторы и соответственно помечены #.

В .NET, поскольку вы просто адресуете счетчик и экземпляр по имени, вам грозит перекрестное обновление. Поскольку .NET берет имя и перечисляет (используя WMI) экземпляры, даже если они используются другим приложением.

Я думаю, что добавление PID * действительно самое умное решение - так как вы оба лучше отслеживаете и не сталкиваетесь. Что касается проблемы с перезагрузкой, создающей новый счетчик, я не вижу проблемы; если вы разрешаете нескольким экземплярам процесса запускать в определенный момент, как бы вы знали, был ли этот экземпляр создан из-за перезагрузки или просто запуска другого исполняемого файла?

Если у вас есть какая-то зависимость между процессами, вы можете очистить устаревшие счетчики или использовать другую логику. В PerfMon вы можете смотреть "*" все экземпляры.

* Или если у вас есть какая-то логика процесса, которая поддерживается без учета перезапусков - например, идентификатор задачи.