13

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

  1. 队列中的项目数
  2. 每秒从队列中移除的项目数

第一个工作正常,第二个在 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();

如前所述 - 如果我在调用 increment 之后放置一个断点,我可以看到 RawValue 不断增加,与对服务的调用一致(相当频繁,我认为每秒不止一次)但性能计数器本身保持打开状态0。

提供“队列”上项目计数的性能计数器以相同的方式实现(尽管我分配了 RawValue,而不是调用增量)工作得很好。

我错过了什么?

4

4 回答 4

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);
    }
}

我希望这可以帮助别人。

于 2011-02-22T02:34:13.980 回答
4

当您使用Average类型性能计数器时,有两个组件 - 分子和分母。因为您使用的是平均值,所以计数器计算为“x 个实例/y 个实例”。在您的情况下,您正在计算每“秒数”的“数字项目”。换句话说,您需要计算从队列中取出的项目数量以及移除它们需要多少秒。

AveragePerformance Counters 类型实际上创建了两个计数器 - 一个称为 的分子组件和一个称为的{name}分母组件{name}Base。如果您转到性能计数器管理单元,您可以查看所有类别和计数器;您可以检查Base柜台的名称。当队列处理过程开始时,你应该

  • 开始秒表
  • 从队列中删除项目
  • 停止秒表
  • {name}计数器增加从队列中删除的项目数
  • {name}Base计数器增加秒表上的刻度数

计数器应该自动知道将第一个计数器除以第二个以给出平均速率。查看CodeProject以了解其工作原理的一个很好的示例。


您很可能不想要这种类型的计数器。这些Average计数器用于确定每秒操作发生多少个实例;例如,完成一个订单或执行一些复杂的交易或流程所需的平均秒数。您可能想要的是“实时”的平均实例数,而不是处理时间。

考虑一下如果您的队列中有 1 个项目,并且需要 1 毫秒来删除,那就是每秒 1000 个项目的速率。但是一秒钟后,您只删除了 1 个项目(因为仅此而已),因此您每秒“实时”处理 1 个项目。同样,如果队列中有 100 万个项目,但您只处理了一个,因为您的服务器正忙于做其他工作,您希望看到 1000 个项目/秒的理论值还是 1 个项目/秒的实际值?

如果您想要这个“真实”数字,而不是理论吞吐量数字,那么这种情况并不适合性能计数器 - 相反,您需要知道开始时间和结束时间,以及处理的项目数量。它不能用一个简单的“计数器”来完成。相反,您将在某处存储系统启动时间,然后计算(number of items) / (now - startup time).

于 2011-02-06T02:54:41.590 回答
1

我有同样的问题。在我的测试中,我相信我看到的问题是多实例和每秒计数率的某种组合。如果我使用单个实例或多个项目计数器,它就可以工作。多实例和每秒速率的组合导致它始终为零。

由于RateOfCountsPerSecond64 类型的性能计数器总是提到值 0,因此重新启动可能会解决问题。反正为我工作。

对我有用的另一件事是在这样的块中初始化计数器:

counter.BeginInit();
counter.RawValue = 0;
counter.EndInit();
于 2017-06-20T22:58:50.480 回答
0

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

因此,如果您希望它对用户唯一,您可以将计数器保存到数据库、平面文件甚至会话变量中。

于 2011-02-06T00:50:56.253 回答