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

StackOverflow https://stackoverflow.com/questions/1622440

  •  06-07-2019
  •  | 
  •  

Вопрос

На этот вопрос уже есть ответ здесь:

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

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

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

Это было полезно?

Решение

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

Другие советы

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top