RateOfCountsPerSecond32类型的计数器始终显示0

时间:2010-02-10 15:56:40

标签: c# performancecounter

我有一个Windows服务,通过WCF服务接口提供某些虚拟队列的消息。 我想公开两个性能计数器 -

  1. 队列中的项目数
  2. 每秒从队列中删除的项目数
  3. 第一个工作正常,第二个在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),但效果很好。

    我错过了什么?

4 个答案:

答案 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)

我认为你需要一些方法来坚持反击。在我看来,每次启动服务调用时都会重新创建计数器。

因此,如果您希望计数器对用户来说是唯一的,那么您可以将计数器保存到数据库,平面文件或甚至是会话变量。