Измерьте время выполнения в С#
Я хочу измерить выполнение фрагмента кода, и мне интересно, какой лучший способ сделать это?
Вариант 1:
DateTime StartTime = DateTime.Now;
//Code
TimeSpan ts = DateTime.Now.Subtract(StartTime);
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");
Вариант 2: используя System.Diagnostics;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
//Code
stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;
// Format and display the TimeSpan value.
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");
Это не просто для бенчмаркинга, его фактическая часть приложения. Время, которое функция выполняет для выполнения, - это релевантные данные. Однако он не должен быть атомарным или гиперточным.
Какой вариант лучше для производственного кода, или кто-то другой использует что-то другое и, возможно, лучше?
Класс Stopwatch
специально разработан для измерения прошедшего времени и может (если он доступен на вашем оборудовании) обеспечить хорошую детализацию/точность с использованием базового высокочастотного аппаратного таймера. Так что это лучший выбор.
Свойство IsHighResolution может использоваться для определения доступности времени высокого разрешения. В документации этот класс предлагает оболочку для "лучших доступных" API Win32 для точного времени:
В частности, поле
Frequency
иGetTimestamp
можно использовать в место неуправляемых API Win32QueryPerformanceFrequency
иQueryPerformanceCounter
.
Подробный справочник по этим API-интерфейсам Win32 [здесь] и в связанных документах MSDN 2.
Таймер с высоким разрешением
Счетчик - это общий термин, используемый в программирования для обозначения увеличивая переменную. Некоторые системы включают высокую производительность счетчик, который обеспечивает высокое разрешение прошедшее время.
Если производительность с высоким разрешением счетчик существует в системе, вы можете используйте QueryPerformanceFrequency функции для выражения частоты в количество в секунду. Значение счетчик зависит от процессора. На некоторых процессоры, например, счетчик может быть скорость цикла процессорные часы.
Функция QueryPerformanceCounter извлекает текущее значение счетчик производительности с высоким разрешением. Вызывая эту функцию на начало и конец раздела кода, приложение по существу использует счетчик как с высоким разрешением таймер. Например, предположим, что Значение QueryPerformanceFrequency указывает что частота счетчик производительности с высоким разрешением 50 000 отсчетов в секунду. Если вызовы приложений QueryPerformanceCounter немедленно до и сразу после раздел кода, который должен быть синхронизирован, значение счетчика может составлять 1500 и 3500 отсчетов, соответственно. Эти значения указывают, что .04 секунды (2000 отсчетов), истек, пока код выполняется.
Это не просто то, что StopWatch
более точно, но также и то, что DateTime.Now
даст некорректные результаты при некоторых обстоятельствах.
Рассмотрим, что происходит во время перехода на летнее время, например, — использование DateTime.Now
может дать отрицательный ответ!
Я обычно использую StopWatch
для такого рода ситуаций.
Из MSDN страница:
Секундомер
Предоставляет набор методов и свойства, которые вы можете использовать для точно измерять прошедшее время.
В следующем посте я использую его для сравнения времени выполнения LINQ vs PLINQ:
Ничто не повредит производительности, потому что вы говорите, что это не так важно. StopWatch кажется более подходящим - вы только вычитаете время от времени, а не одну дату от другой. Материал даты занимает немного больше памяти и процессорное время. Существуют также способы сделать код чище, если вы планируете повторно использовать его в нескольких местах. Перегрузка using
приходит на ум. Я буду искать пример. Хорошо, код украден из:
http://stevesmithblog.com/blog/great-uses-of-using-statement-in-c/
public class ConsoleAutoStopWatch : IDisposable
{
private readonly Stopwatch _stopWatch;
public ConsoleAutoStopWatch()
{
_stopWatch = new Stopwatch();
_stopWatch.Start();
}
public void Dispose()
{
_stopWatch.Stop();
TimeSpan ts = _stopWatch.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");
}
}
private static void UsingStopWatchUsage()
{
Console.WriteLine("ConsoleAutoStopWatch Used: ");
using (new ConsoleAutoStopWatch())
{
Thread.Sleep(3000);
}
}
У меня есть небольшой класс, чтобы делать такие вещи ad hoc. Он использует класс секундомера - С# micro perfomance testing.
например.
var tester = new PerformanceTester(() => SomeMethod());
tester.MeasureExecTime(1000);
Console.Writeline(string.Format("Executed in {0} milliseconds", tester.AverageTime.TotalMilliseconds));
Оба, скорее всего, будут соответствовать вашим потребностям, но я бы сказал, используйте StopWatch
. Зачем? Потому что это предназначено для задачи, которую вы делаете.
У вас есть один класс, построенный для возврата текущей даты/времени, который, как это бывает, может использоваться для синхронизации вещей, и у вас есть один класс, специально предназначенный для синхронизации событий.
В этом случае различия существуют только в случае, если вам нужна точность в миллисекундах (в каком случае StopWatch
более точная), но в качестве общего принципала, если инструмент существует специально для задачи, которую вы ищете, тем лучше один для использования.
Я взял ответ Хэмиша, упростил его и сделал его более общим, если вам нужно зайти в другое место:
public class AutoStopWatch : Stopwatch, IDisposable {
public AutoStopWatch() {
Start();
}
public virtual void Dispose() {
Stop();
}
}
public class AutoStopWatchConsole : AutoStopWatch {
private readonly string prefix;
public AutoStopWatchConsole(string prefix = "") {
this.prefix = prefix;
}
public override void Dispose() {
base.Dispose();
string format = Elapsed.Days > 0 ? "{0} days " : "";
format += "{1:00}:{2:00}:{3:00}.{4:00}";
Console.WriteLine(prefix + " " + format.Format(Elapsed.Days, Elapsed.Hours, Elapsed.Minutes, Elapsed.Seconds, Elapsed.Milliseconds / 10));
}
}
private static void Usage() {
Console.WriteLine("AutoStopWatch Used: ");
using (var sw = new AutoStopWatch()) {
Thread.Sleep(3000);
Console.WriteLine(sw.Elapsed.ToString("h'h 'm'm 's's'"));
}
Console.WriteLine("AutoStopWatchConsole Used: ");
using (var sw = new AutoStopWatchConsole()) {
Thread.Sleep(3000);
}
}
Используйте ниже код
DateTime dExecutionTime;
dExecutionTime = DateTime.Now;
TimeSpan span = DateTime.Now.Subtract(dExecutionTime);
lblExecutinTime.Text = "total time taken " + Math.Round(span.TotalMinutes,2) + " minutes . >>---> " + DateTime.Now.ToShortTimeString();
- Вопросы
- Execution-time
- Измерьте время выполнения в С#