Вызов методов тестирования в C #

Я ищу способ тестирования вызовов методов на C #.

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

Теперь я хочу сравнить обе версии с тестовыми данными, чтобы увидеть, стоит ли проводить оптимизацию. Я знаю, что в Ruby вы можете обернуть код в блок Benchmark и заставить его выводить время, необходимое для выполнения блока в консоли - есть ли что-то подобное для C #?


person Toms Mikoss    schedule 25.10.2009    source источник


Ответы (6)


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

person mike    schedule 25.10.2009
comment
секундомер - не лучший способ Бенчмарка. Он использует регистры процессора, поэтому ваш собственный код не может его использовать. Вы можете тестировать код с секундомером и без него, и разница до 3 раз. - person Evgeniy; 15.12.2015

Похищено (и модифицировано) из ответа Юрия:

private static void Benchmark(Action act, int iterations)
{
    GC.Collect();
    act.Invoke(); // run once outside of loop to avoid initialization costs
    Stopwatch sw = Stopwatch.StartNew();
    for (int i = 0; i < iterations; i++)
    {
        act.Invoke();
    }
    sw.Stop();
    Console.WriteLine((sw.ElapsedMilliseconds / iterations).ToString());
}

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

person MusiGenesis    schedule 25.10.2009
comment
Отлично, я просто искал метод быстрого тестирования C #. - person Yuriy Faktorovich; 07.03.2013
comment
И нашли ответ, основанный на одном из ваших ответов? StackOverflow существует уже достаточно давно, и это случалось со мной несколько раз: мимо меня отвечает на вопрос, который задает я. - person MusiGenesis; 07.03.2013
comment
Пример: Benchmark(() => { /* your code */ }, 100); - person 2Toad; 22.12.2015

Я украл большую часть следующего из метода бенчмаркинга Джона Скита:

private static void Benchmark(Action act, int interval)
{
    GC.Collect();
    Stopwatch sw = Stopwatch.StartNew();
    for (int i = 0; i < interval; i++)
    {
        act.Invoke();
    }
    sw.Stop();
    Console.WriteLine(sw.ElapsedMilliseconds);
}
person Yuriy Faktorovich    schedule 25.10.2009
comment
Добавление локального GC.Collect () может привести к тому, что вы пропустите проблемы с глобальным распределением памяти, которые влияют на производительность, однако это сделает локальные измерения более точными. - person Danny Varod; 26.10.2009

Вот некоторые вещи, которые я обнаружил методом проб и ошибок.

  1. Откажитесь от первой партии (тысяч) итераций. Скорее всего, на них повлияет JITter.
  2. Выполнение теста на отдельном Thread объекте может дать лучшие и более стабильные результаты. Не знаю почему.
  3. Я видел, как некоторые люди использовали Thread.Sleep по какой-либо причине перед выполнением теста. Это только усугубит ситуацию. Не знаю почему. Возможно, из-за JITter.
  4. Никогда не запускайте тест с включенной отладкой. Код, скорее всего, будет работать на порядки медленнее.
  5. Скомпилируйте свое приложение со всеми включенными оптимизациями. На некоторый код оптимизация может существенно повлиять, а на другой - нет, поэтому компиляция без оптимизации повлияет на надежность вашего теста.
  6. При компиляции с включенной оптимизацией иногда необходимо как-то оценить результат теста (например, распечатать значение и т. Д.). В противном случае компилятор может «понять», что некоторые вычисления бесполезны, и просто не будет их выполнять.
  7. Вызов делегатов может иметь заметные накладные расходы при выполнении определенных тестов. Лучше поместить в делегат несколько итераций, чтобы накладные расходы мало влияли на результат теста.
  8. Профилировщики могут иметь свои собственные накладные расходы. Они умеют говорить вам, какие части вашего кода являются узкими местами, но не умеют надежно тестировать две разные вещи.
  9. В общем, модные решения для тестирования производительности могут иметь заметные накладные расходы. Например, если вы хотите протестировать множество объектов с помощью одного интерфейса, может возникнуть соблазн обернуть каждый объект в класс. Однако помните, что конструктор класса также имеет накладные расходы, которые необходимо учитывать. Лучше сделать все максимально простым и прямым.
person GregRos    schedule 12.03.2013

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

person Noldorin    schedule 25.10.2009

Профилировщики дают лучшие тесты, поскольку они диагностируют весь ваш код, однако они сильно его замедляют. Профилировщики используются для поиска узких мест.

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

person Danny Varod    schedule 25.10.2009