Как проверить, какой метод работает быстрее?

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

Reed Copsey предоставил решение, используя Char.IsLetter:

string myString = "RandomStringOfLetters";
bool allLetters = myString.All( c => Char.IsLetter(c) );

Адаптированное решение с использованием регулярных выражений от Mark Byers:

string s = "RandomStringOfLetters";
bool allLetters = Regex.IsMatch(s, "^[a-z]+$", RegexOptions.IgnoreCase);

Не желая просто задавать вопрос ни Риду, ни Марку, я решил написать быстрый тест, чтобы определить, какие из них лучше. Проблема в том, что я не много занимался оптимизацией кода (я склонен ставить читабельность кода выше всего остального).

Помимо выбора временной отметки до и после запуска каждого, какие еще (лучше?) Варианты определения того, какое решение работает быстрее?

редактировать

Я изменил ответ Мартина, чтобы работать с Console.WriteLine(...) и запустил его как консольное приложение. Не уверен, как именно LinqPad запускает приложения, но результаты были примерно одинаковыми:

41
178

6 ответов

Решение

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

  1. Всегда проводите тест более 1 раза. В первый раз, когда вы запустите его, из JIT будут накладные расходы, и время может ввести в заблуждение. Хороший подход - многократный прогон и получение среднего значения (например, я часто провожу такой тест 100000 раз).
  2. Всегда запускайте тест с полной версией выпуска вне процесса размещения Visual Studio. (По умолчанию вы можете использовать для этого Ctrl+F5.) Хост Visual Studio существенно влияет на время.

Вы должны проверить System.Diagnostics.Stopwatch!

http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx

Вы должны выполнить это много раз в цикле, чтобы уменьшить ошибки синхронизации и другие неконтролируемые факторы.

Надеюсь, это поможет.

Я просто собрал это в LINQPad в качестве примера того, как я это сделаю (отсюда вызовы Dump() - Замените на Console.WriteLine(...), если вы не используете этот удобный инструмент).

Похоже, что способ LINQ чуть более чем в четыре раза быстрее:

System.Diagnostics.Stopwatch stopwatch = new Stopwatch();

stopwatch.Start();
for (int i = 0; i < 100000; i++)
{
 string myString = "RandomStringOfLetters";
 bool allLetters = myString.All( c => Char.IsLetter(c) );
}
stopwatch.Stop();
stopwatch.ElapsedMilliseconds.Dump();

stopwatch.Reset();

stopwatch.Start();
for (int i = 0; i < 100000; i++)
{
 string s = "RandomStringOfLetters";
 bool allLetters = Regex.IsMatch(s, "^[a-z]+$", RegexOptions.IgnoreCase);
}
stopwatch.Stop();
stopwatch.ElapsedMilliseconds.Dump();

Выход:

47 
196

Существует класс System.Diagnostics.Stopwatch, который можно использовать.

Какой бы код вы ни тестировали, запустите тест один раз, чтобы убрать JIT-затраты, а затем снова запустите его для окончательного времени. Большинство отдельных отсчетов времени могут быть непредставительными из-за других факторов на ПК - поэтому проведите много итераций и затем рассчитайте среднее время выполнения из этого.

Шаги, чтобы определить, что быстрее:

  1. Получить коллекцию компьютеров, пару сотен должны сделать, AMD/Intel/ другие,32-разрядные /64-разрядные, ...

  2. Установите каждый.NET Framework, который вам нужен, на каждом из них (по очереди)

  3. Попробуйте каждую комбинацию параметров оптимизации для компиляции (по очереди)

  4. Используйте StopWatch для тестирования большого прогона для каждого

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

Это может дать вам некоторое представление о том, что быстрее на практике, по крайней мере, для текущих выпусков компилятора. Повторите с каждым новым выпуском компилятора.

Используйте класс System.Diagnostics.Stopwatch.

Запустите StopWatch и выполните несколько тысяч итераций, остановите его и проверьте общее количество прошедших миллисекунд

Другие вопросы по тегам