我有一个Windows服务,通过WCF服务接口提供某些虚拟队列的消息。 我想公开两个性能计数器 -
第一个工作正常,第二个在PerfMon.exe中始终显示为0,尽管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),但效果很好。
我错过了什么?
答案 0 :(得分:15)
我最初也遇到过这个问题的问题。 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);
}
}
我希望这有助于某人。
答案 1 :(得分:4)
当您使用Average
类型性能计数器时,有两个组件 - 分子和分母。因为您使用的是平均值,所以计数器计算为“每y个实例的x个实例”。在您的情况下,您每个'秒数'计算'数字项'。换句话说,您需要计算从队列中取出的项目数以及要删除它们的秒数。
Average
类型的性能计数器实际上创建了两个计数器 - 一个名为{name}
的分子组件和一个名为{name}Base
的分母组件。如果转到“性能计数器”管理单元,则可以查看所有类别和计数器;您可以查看Base
计数器的名称。当队列处理过程开始时,你应该
{name}
计数器增加从队列中删除的项目数{name}Base
计数器增加秒表上的刻度数计数器应该自动知道将第一个计数器除以秒来得到平均速率。请查看CodeProject,了解其工作原理。
你很可能不想要这种类型的计数器。这些Average
计数器用于确定每秒操作发生的实例数;例如完成订单或执行复杂事务或流程所需的平均秒数。您可能想要的是“实际”时间的平均实例数,而不是处理时间。
考虑你的队列中是否有1个项目,需要1ms才能删除,这是每秒1000个项目的速度。但是在一秒之后你只删除了1个项目(因为那就是全部),所以你在'实际'时间内每秒处理1个项目。同样,如果队列中有一百万个项目,但由于您的服务器忙于完成其他工作,您只处理了一个项目,您是否希望看到1000项/秒理论值或1项/秒真实?
如果您想要这个'真实'数字,而不是理论吞吐量数字,那么这种情况并不适合性能计数器 - 而是需要知道开始时间,结束时间和许多项目处理。用一个简单的“计数器”来实现它是不可能的。相反,您可以在某处存储系统启动时间,并计算(number of items) / (now - startup time)
。
答案 2 :(得分:1)
我遇到了同样的问题。在我的测试中,我相信我看到的问题是多实例和每秒计数率的某种组合。如果我使用单个实例或许多项目反击它工作。关于多实例和每秒速率的组合使得它总是为零。
正如Performance counter of type RateOfCountsPerSecond64 has always the value 0提到的那样,重新启动可能会起到作用。无论如何,为我工作。
另一件对我有用的事情就是在这样的块中初始化计数器:
counter.BeginInit();
counter.RawValue = 0;
counter.EndInit();
答案 3 :(得分:0)
我认为你需要一些方法来坚持反击。在我看来,每次启动服务调用时都会重新创建计数器。
因此,如果您希望计数器对用户来说是唯一的,那么您可以将计数器保存到数据库,平面文件或甚至是会话变量。