Метод бенчмаркинга вызывает С#

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

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

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

Ответы

Ответ 1

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

Ответ 2

Украден (и изменен) из ответа Юрия:

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

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

Ответ 3

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

  • Отменить первую партию (тысяч) итераций. Они, скорее всего, будут затронуты JITter.
  • Запуск теста на отдельном объекте Thread может дать лучшие и более стабильные результаты. Я не знаю, почему.
  • Я видел, как некоторые люди использовали Thread.Sleep по какой-либо причине перед выполнением теста. Это только ухудшит ситуацию. Я не знаю почему. Возможно, из-за JITter.
  • Никогда не запускайте тест с включенной отладкой. Код, скорее всего, будет работать на порядки медленнее.
  • Скомпилируйте приложение со всеми включенными оптимизациями. Некоторый код может сильно повлиять на оптимизацию, в то время как другого кода не будет, поэтому компиляция без оптимизации повлияет на надежность вашего теста.
  • При компиляции с включенными оптимизациями иногда необходимо как-то оценить результат теста (например, напечатать значение и т.д.). В противном случае компилятор может "вычислить", некоторые вычисления бесполезны и просто не будут выполнять их.
  • Вызов делегатов может иметь заметные накладные расходы при выполнении определенных тестов. Лучше поставить в делегат несколько итераций, так что накладные расходы мало влияют на результат эталона.
  • Профилировщики могут иметь свои собственные накладные расходы. Они хорошо говорят вам, какие части вашего кода являются узкими местами, но они не очень хороши для сравнения двух разных вещей.
  • В общем, причудливые решения для бенчмаркинга могут иметь заметные накладные расходы. Например, если вы хотите сравнить многие объекты с помощью одного интерфейса, может возникнуть соблазн обернуть каждый объект в классе. Однако помните, что конструктор класса также имеет накладные расходы, которые необходимо учитывать. Лучше держать все как можно проще и проще.

Ответ 4

Я украл большую часть следующего из метода Jon Skeet для бенчмаркинга:

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

Ответ 5

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

Ответ 6

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

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