Why is the graph spiky when using average?

这一生的挚爱 提交于 2019-12-01 11:32:24

The problem is, that the AverageTimer32 doesn't show some alltime average value. From the documentation:

An average counter that measures the time it takes, on average, to complete a process or operation. Counters of this type display a ratio of the total elapsed time of the sample interval to the number of processes or operations completed during that time. This counter type measures time in ticks of the system clock. Formula: ((N1 - N0)/F)/(B1 - B0), where N1 and N0 are performance counter readings, B1 and B0 are their corresponding AverageBase values, and F is the number of ticks per second.

The interesting part is the formula. The performance counter just shows the average between two performance counter readings. So if no requests where made, the resulting value is 0 because the numerator is 0.

Maybe it's somehow possible to calculate the value on your own and expose it through some other type of performance counter.

EDIT: I wrote a demo application to demonstrate a workaround, but it feels quite messy. I created an NumberOfItems32 performance counter.

var counterDataCollection = new CounterCreationDataCollection();

var averageRandomNumer = new CounterCreationData
{
    CounterType = PerformanceCounterType.NumberOfItems32,
    CounterName = averageRandomNumberCounterName,
    CounterHelp = "Views the average random number."
};
counterDataCollection.Add(averageRandomNumer);

PerformanceCounterCategory.Create(
    categoryName,
    "Displays the various performance counters of a test application",
    PerformanceCounterCategoryType.MultiInstance,
    counterDataCollection);

And set the value like so:

var averageRandomNumberPerfCounter = new PerformanceCounter(categoryName, averageRandomNumberCounterName, "firstInstance", false);
var random = new Random();
var currentAverage = 0d;
var numberOfReadings = 0L;

while (true)
{
    var nextRandom = random.Next(1, 101);

    // ATTENTION: real code should handle overflow properly
    numberOfReadings++;
    currentAverage = (((numberOfReadings - 1) * currentAverage) + nextRandom) / numberOfReadings;

    averageRandomNumberPerfCounter.RawValue = (long)currentAverage;

    Thread.Sleep(1000);
}

The disadvantage of this solution is obvious. Since the performance counter can only store long you lose the decimal places of your average value. Another workaround for this problem would be to scale your values, for example multiplying them with 10 and then choose an lower scaling in performance monitor.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!