Именование счетчиков производительности нескольких экземпляров в .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 вы можете смотреть "*" все экземпляры.
* Или если у вас есть какая-то логика процесса, которая поддерживается без учета перезапусков - например, идентификатор задачи.