Подтвердить что ты не робот

Измерьте время выполнения в С#

Я хочу измерить выполнение фрагмента кода, и мне интересно, какой лучший способ сделать это?

Вариант 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");

Это не просто для бенчмаркинга, его фактическая часть приложения. Время, которое функция выполняет для выполнения, - это релевантные данные. Однако он не должен быть атомарным или гиперточным.

Какой вариант лучше для производственного кода, или кто-то другой использует что-то другое и, возможно, лучше?

4b9b3361

Ответ 1

Класс Stopwatch специально разработан для измерения прошедшего времени и может (если он доступен на вашем оборудовании) обеспечить хорошую детализацию/точность с использованием базового высокочастотного аппаратного таймера. Так что это лучший выбор.

Свойство IsHighResolution может использоваться для определения доступности времени высокого разрешения. В документации этот класс предлагает оболочку для "лучших доступных" API Win32 для точного времени:

В частности, поле Frequency и GetTimestamp можно использовать в место неуправляемых API Win32 QueryPerformanceFrequency и QueryPerformanceCounter.

Подробный справочник по этим API-интерфейсам Win32 [здесь] и в связанных документах MSDN 2.

Таймер с высоким разрешением

Счетчик - это общий термин, используемый в программирования для обозначения увеличивая переменную. Некоторые системы включают высокую производительность счетчик, который обеспечивает высокое разрешение прошедшее время.

Если производительность с высоким разрешением счетчик существует в системе, вы можете используйте QueryPerformanceFrequency функции для выражения частоты в количество в секунду. Значение счетчик зависит от процессора. На некоторых процессоры, например, счетчик может быть скорость цикла процессорные часы.

Функция QueryPerformanceCounter извлекает текущее значение счетчик производительности с высоким разрешением. Вызывая эту функцию на начало и конец раздела кода, приложение по существу использует счетчик как с высоким разрешением таймер. Например, предположим, что Значение QueryPerformanceFrequency указывает что частота счетчик производительности с высоким разрешением 50 000 отсчетов в секунду. Если вызовы приложений QueryPerformanceCounter немедленно до и сразу после раздел кода, который должен быть синхронизирован, значение счетчика может составлять 1500 и 3500 отсчетов, соответственно. Эти значения указывают, что .04 секунды (2000 отсчетов), истек, пока код выполняется.

Ответ 2

Это не просто то, что StopWatch более точно, но также и то, что DateTime.Now даст некорректные результаты при некоторых обстоятельствах.

Рассмотрим, что происходит во время перехода на летнее время, например, — использование DateTime.Now может дать отрицательный ответ!

Ответ 3

Я обычно использую StopWatch для такого рода ситуаций.

Из MSDN страница:

Секундомер

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

В следующем посте я использую его для сравнения времени выполнения LINQ vs PLINQ:

Параллельный LINQ (PLINQ) с Visual Studio 2010

Ответ 4

Ничто не повредит производительности, потому что вы говорите, что это не так важно. 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);
    }
}

Ответ 5

Оба, скорее всего, будут соответствовать вашим потребностям, но я бы сказал, используйте StopWatch. Зачем? Потому что это предназначено для задачи, которую вы делаете.

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

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

Ответ 6

У меня есть небольшой класс, чтобы делать такие вещи ad hoc. Он использует класс секундомера - С# micro perfomance testing.

например.

var tester = new PerformanceTester(() => SomeMethod());
tester.MeasureExecTime(1000);
Console.Writeline(string.Format("Executed in {0} milliseconds", tester.AverageTime.TotalMilliseconds));

Ответ 7

Используйте ниже код

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

Ответ 8

Я взял ответ Хэмиша, упростил его и сделал его более общим, если вам нужно зайти в другое место:

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

}