Почему график выглядит остроконечным при использовании среднего значения?

Я использую messageInspectors в моей службе WCF для измерения прошедшего времени для каждого метода службы, например:

public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
    if (_activated)
    {
        _startTime.Stop();
        PerformanceCounterHandler.Instance.SetAveragePerformanceCounter(operationName, _startTime.ElapsedTicks);
    }
}

public object BeforeCall(string operationName, object[] inputs)
{
    Guid correlationState;

    if (_activated)
    {
        correlationState = Guid.NewGuid();
        _startTime = new Stopwatch();
        _startTime.Start();
        return correlationState;
    }
    return null;
}

Так регистрируются счетчики

foreach (string methodName in ServiceMethodNames)
                {
                    counter = new CounterCreationData(methodName, methodName + " > Genomsnittlig tid(ms)", PerformanceCounterType.AverageTimer32);
                    col.Add(counter);
                    counter = new CounterCreationData(methodName + "_base", methodName + " > Genomsnittlig tid(ms)", PerformanceCounterType.AverageBase);
                    col.Add(counter);
                }

Метод установки счетчика производительности выглядит следующим образом:

public Boolean SetAveragePerformanceCounter(string performanceCounterName, long value)
        {
            PerformanceCounter performCounter;

            if (_useOrbitPerformanceCounters && (performCounter = _performanceCounters.Values.Where(c=> c.CounterName == performanceCounterName).FirstOrDefault()) != null)
            {
                performCounter.IncrementBy(value);
                performanceCounterName = performanceCounterName + "_base";
                performCounter = _performanceCounters[performanceCounterName];
                performCounter.Increment();
                return true;
            }
            return false;
        }

Однако счетчик производительности показывает пики вместо среднего? Если я изменю представление, чтобы сообщить, что все равно 0, пока я ничего не делаю? Мне нужно иметь возможность видеть, как выглядит среднее время звонков прямо сейчас, даже если в данный момент звонков нет. Что я делаю неправильно?

Счетчик производительности


person Banshee    schedule 10.06.2015    source источник


Ответы (1)


Проблема в том, что AverageTimer32 не показывает среднее значение за все время. Из документации :

Счетчик средних значений, который измеряет время, которое в среднем требуется для завершения процесса или операции. Счетчики этого типа отображают отношение общего прошедшего времени интервала выборки к количеству процессов или операций, выполненных за это время. Этот тип счетчика измеряет время в тиках системных часов. Формула: ((N1 — N0)/F)/(B1 — B0), где N1 и N0 — показания счетчика производительности, B1 и B0 — соответствующие им значения AverageBase, а F — количество тактов в секунду.

Самое интересное - это формула. Счетчик производительности просто показывает среднее значение между двумя показаниями счетчика производительности. Таким образом, если запросы не поступали, результирующее значение равно 0, поскольку числитель равен 0.

Может быть, как-то можно вычислить значение самостоятельно и выставить его через какой-то другой тип счетчика производительности.

РЕДАКТИРОВАТЬ: я написал демонстрационное приложение, чтобы продемонстрировать обходной путь, но оно кажется довольно грязным. Я создал счетчик производительности NumberOfItems32.

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

И установите значение так:

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

Недостаток этого решения очевиден. Поскольку счетчик производительности может хранить только long, вы теряете десятичные разряды своего среднего значения. Другим обходным путем для этой проблемы может быть масштабирование ваших значений, например, умножение их на 10, а затем выбор более низкого масштабирования в мониторе производительности.

person Thomas Lielacher    schedule 10.06.2015
comment
Спасибо, вопрос в том, какой тип счетчика производительности я должен использовать вместо этого? - person Banshee; 10.06.2015