Самопрофилирование с использованием класса Proxy - PullRequest
0 голосов
/ 16 февраля 2009

Учитывая интерфейс

public interface IValueProvider
{
  object GetValue(int index);
}

и древовидная структура экземпляров IValueProvider, аналогичная дереву математических выражений. Я хочу измерить время, которое тратится в методе GetValue каждого узла во время выполнения без внешнего профилировщика.

GetValue может делать все, что я не знаю во время разработки: собирать значения из других IValueProviders, запускать выражение IronPython или даже быть внешним плагином. Я хочу представить статистику о времени узлов пользователю.

Для этого я могу создать прокси-класс, который оборачивает IValueProvider:

public class ValueProviderProfiler : IValueProvider
{
  private IValueProvider valueProvider;

  public object GetValue(int index)
  {
    // ... start measuring
    try
    {
      return this.valuepProvider.GetValue(index);
    }
    finally
    {
      // ... stop measuring
    }
  }
}

Каков наилучший способ измерить время, проведенное в узле без искажений, вызванных внешними процессами, с хорошей точностью и с учетом того факта, что узлы оцениваются параллельно?

Простое использование класса Stopwatch не сработает, а анализ времени процессора не учитывает тот факт, что время процессора могло быть использовано на другом узле.

Ответы [ 2 ]

1 голос
/ 16 февраля 2009

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

0 голосов
/ 16 февраля 2009

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

Для вещей, которые занимают определенное количество миллисекунд (доступ к диску, заполнение элементов управления, передача по сети и т. Д.), Я использовал DateTime.Ticks.Now. Кажется, он работает достаточно хорошо, и заявленное разрешение 10 000 000 тиков в секунду звучит довольно хорошо. (Я сомневаюсь, что это действительно так точно; я не знаю, на каком объекте это поддерживается.)

Я не знаю ни одного способа избежать искажений, вызванных выполнением других процессов. Обычно я просто беру среднее время, затрачиваемое на выполнение каждого интересующего меня раздела, усредняется по максимально возможному количеству запусков (чтобы сгладить изменения, вызванные другими процессами и любыми неточностями таймера).

(В нативном коде для профилирования вещей, выполнение которых не занимает много времени, я использую счетчик циклов ЦП с помощью инструкции RDTSC. Поэтому, если вы рассчитываете время, которое слишком рано для других таймеров, чтобы его получить полезное чтение, но оно не заканчивается так быстро, что проблемы с вызовами являются проблемой, и вы не возражаете получать показания в циклах ЦП, а не в стандартных единицах времени, возможно, стоит написать небольшую встроенную функцию, которая возвращает цикл значение счетчика в UInt64. Мне не нужно было делать это в управляемом коде сам, хотя ...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...