Счетчик типа RateOfCountsPerSecond32 всегда показывает 0
У меня есть служба Windows, которая обслуживает сообщения некоторой виртуальной очереди через служебный интерфейс WCF.
Я хотел разоблачить два счетчика производительности -
- Количество элементов в очереди
- Количество элементов, удаленных из очереди в секунду
Первый работает отлично, второй всегда отображается как 0 в PerfMon.exe, несмотря на то, что RawValue выглядит правильно.
Я создаю счетчики как таковые -
internal const string PERF_COUNTERS_CATEGORY = "HRG.Test.GDSSimulator";
internal const string PERF_COUNTER_ITEMSINQUEUE_COUNTER = "# Messages on queue";
internal const string PERF_COUNTER_PNR_PER_SECOND_COUNTER = "# Messages read / sec";
if (!PerformanceCounterCategory.Exists(PERF_COUNTERS_CATEGORY))
{
System.Diagnostics.Trace.WriteLine("Creating performance counter category: " + PERF_COUNTERS_CATEGORY);
CounterCreationDataCollection counters = new CounterCreationDataCollection();
CounterCreationData numberOfMessagesCounter = new CounterCreationData();
numberOfMessagesCounter.CounterHelp = "This counter provides the number of messages exist in each simulated queue";
numberOfMessagesCounter.CounterName = PERF_COUNTER_ITEMSINQUEUE_COUNTER;
numberOfMessagesCounter.CounterType = PerformanceCounterType.NumberOfItems32;
counters.Add(numberOfMessagesCounter);
CounterCreationData messagesPerSecondCounter= new CounterCreationData();
messagesPerSecondCounter.CounterHelp = "This counter provides the number of messages read from the queue per second";
messagesPerSecondCounter.CounterName = PERF_COUNTER_PNR_PER_SECOND_COUNTER;
messagesPerSecondCounter.CounterType = PerformanceCounterType.RateOfCountsPerSecond32;
counters.Add(messagesPerSecondCounter);
PerformanceCounterCategory.Create(PERF_COUNTERS_CATEGORY, "HRG Queue Simulator performance counters", PerformanceCounterCategoryType.MultiInstance,counters);
}
Затем на каждом служебном вызове я увеличиваю соответствующий счетчик, для счетчика в секунду/сек, который в настоящее время выглядит следующим образом:
messagesPerSecCounter = new PerformanceCounter();
messagesPerSecCounter.CategoryName = QueueSimulator.PERF_COUNTERS_CATEGORY;
messagesPerSecCounter.CounterName = QueueSimulator.PERF_COUNTER_PNR_PER_SECOND_COUNTER;
messagesPerSecCounter.MachineName = ".";
messagesPerSecCounter.InstanceName = this.ToString().ToLower();
messagesPerSecCounter.ReadOnly = false;
messagesPerSecCounter.Increment();
Как уже упоминалось - если я ставлю точку останова после вызова для увеличения, я вижу, что RawValue постоянно увеличивается, в соответствии с вызовами службы (довольно часто, более одного раза в секунду, я думаю)
Но сам счетчик производительности остается на 0.
Счетчик производительности, обеспечивающий подсчет элементов в очереди, который реализуется одинаково (хотя я назначаю RawValue, а не Increment вызова), работает просто отлично.
Что мне не хватает?
Ответы
Ответ 1
У меня также были проблемы с этим счетчиком. MSDN имеет полный рабочий пример, который очень помог мне:
http://msdn.microsoft.com/en-us/library/4bcx21aa.aspx
Поскольку их пример был довольно длинным, я откидывал его до одного метода, чтобы продемонстрировать простые вещи. При запуске в PerfMon я вижу ожидаемое значение в 10 отсчетов в секунду.
public static void Test()
{
var ccdc = new CounterCreationDataCollection();
// add the counter
const string counterName = "RateOfCountsPerSecond64Sample";
var rateOfCounts64 = new CounterCreationData
{
CounterType = PerformanceCounterType.RateOfCountsPerSecond64,
CounterName = counterName
};
ccdc.Add(rateOfCounts64);
// ensure category exists
const string categoryName = "RateOfCountsPerSecond64SampleCategory";
if (PerformanceCounterCategory.Exists(categoryName))
{
PerformanceCounterCategory.Delete(categoryName);
}
PerformanceCounterCategory.Create(categoryName, "",
PerformanceCounterCategoryType.SingleInstance, ccdc);
// create the counter
var pc = new PerformanceCounter(categoryName, counterName, false);
// send some sample data - roughly ten counts per second
while (true)
{
pc.IncrementBy(10);
System.Threading.Thread.Sleep(1000);
}
}
Я надеюсь, что это поможет кому-то.
Ответ 2
Когда вы работаете с счетчиками производительности Average
, есть два компонента - числитель и знаменатель. Поскольку вы работаете со средним значением, счетчик вычисляется как "x экземпляров на y экземпляров". В вашем случае вы разрабатываете "количество элементов" за "количество секунд". Другими словами, вам нужно учитывать как количество элементов, которые вы вынимаете из очереди, так и сколько секунд они должны быть удалены.
Счетчики производительности Average
фактически создают два счетчика - компонент числителя под названием {name}
и компонент знаменателя, называемый {name}Base
. Если вы заходите в оснастку "Счетчик производительности", вы можете просмотреть все категории и счетчики; вы можете проверить имя счетчика Base
. Когда процесс обработки очереди запущен, вы должны
- начать секундомер
- удалить элементы из очереди
- остановить секундомер
- увеличивать счетчик
{name}
на количество элементов, удаленных из очереди
- увеличивайте счетчик
{name}Base
на количество тиков на секундомере
Счетчик должен автоматически знать, чтобы разделить первый счетчик на второй, чтобы дать среднюю ставку. Проверьте CodeProject для хорошего примера того, как это работает.
Скорее всего, вам не нужен этот тип счетчика. Эти счетчики Average
используются для определения того, сколько экземпляров происходит за секунду работы; например среднее количество секунд, которое требуется для завершения заказа, или выполнить сложную транзакцию или процесс. То, что вы можете захотеть, - это среднее количество экземпляров в "реальном" времени, а не время обработки.
Подумайте, было ли у вас 1 элемент в вашей очереди, и потребовалось 1 мс, чтобы удалить 1000 пунктов в секунду. Но через одну секунду вы удалили только 1 элемент (потому что все это есть), и поэтому вы обрабатываете 1 элемент в секунду в "реальном" времени. Точно так же, если в очереди есть миллион элементов, но вы только обрабатывали их, потому что ваш сервер занят какой-то другой работой, вы хотите увидеть 1000 статей в секунду или один предмет/второй реальный?
Если вам нужна эта "реальная" цифра, а не теоретическая пропускная способность, то этот сценарий не подходит для счетчиков производительности - вместо этого вам нужно знать время начала и время окончания, а также количество элементов обработанный. Это не может быть сделано с помощью простого "счетчика". Вместо этого вы должны где-то сохранить время запуска системы и вычислить (number of items) / (now - startup time)
.
Ответ 3
Я думаю, вам нужно некоторое время, чтобы упорствовать в стойке. Мне кажется, что каждый раз, когда инициируется служебный вызов, счетчик воссоздается.
Таким образом, вы можете сохранить счетчик в DB, плоском файле или, возможно, даже в переменной сеанса, если хотите, чтобы он был уникальным для пользователя.
Ответ 4
У меня была та же проблема. В моем тестировании я считаю, что я видел, что проблема заключалась в сочетании нескольких экземпляров и скорости подсчета в секунду. Если я использовал один экземпляр или счетчик элементов, он работал. Что-то в этой комбинации из нескольких экземпляров и скорости в секунду приводило к тому, что она всегда была нулевой.
Как Счетчик производительности типа RateOfCountsPerSecond64 всегда имеет значение 0, перезагрузка может сделать трюк. Все равно работал у меня.
Еще одна вещь, которая сработала для меня, - это инициализация счетчика в блоке, подобном этому:
counter.BeginInit();
counter.RawValue = 0;
counter.EndInit();