Measure execution time in C#

2019-01-22 01:27发布

I want to measure the execution of a piece of code and I'm wondering what the best method to do this is?

Option 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");

Option 2: using 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");

This isn't simply for benchmarking, its actually part of the application. The time the function takes to execute is relevant data. It doesn't however need to be atomic or hyper-accurate.

Which option is better for production code, or does anybody else use something different and perhaps better?

8条回答
We Are One
2楼-- · 2019-01-22 02:03

I took Hamish's answer simplified it and made it a bit more general in case you need to log to somewhere else:

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

}
查看更多
Juvenile、少年°
3楼-- · 2019-01-22 02:10

Use below code

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();
查看更多
Juvenile、少年°
4楼-- · 2019-01-22 02:11

It's not just that StopWatch is more accurate, but also that DateTime.Now will give incorrect results in some circumstances.

Consider what happens during a daylight saving time switch-over, for example — using DateTime.Now can actually give a negative answer!

查看更多
孤傲高冷的网名
5楼-- · 2019-01-22 02:12

I have a little class to do this sort of thing ad hoc. It uses the stopwatch class - c# micro perfomance testing.

eg.

var tester = new PerformanceTester(() => SomeMethod());
tester.MeasureExecTime(1000);
Console.Writeline(string.Format("Executed in {0} milliseconds", tester.AverageTime.TotalMilliseconds));
查看更多
放荡不羁爱自由
6楼-- · 2019-01-22 02:18

The Stopwatch class is specifically designed to measure elapsed time and may (if available on your hardware) provide good granularity/accuracy using an underlying high-frequency hardware timer. So this seem the best choice.

The IsHighResolution property can be used to determine whether high resolution timing is available. Per the documentation, this class offers a wrapper on the 'best available' Win32 APIs for accurate timing:

Specifically, the Frequency field and GetTimestamp method can be used in place of the unmanaged Win32 APIs QueryPerformanceFrequency and QueryPerformanceCounter.

There is detailed background on those Win32 APIs [here] and in linked MSDN docs 2.

High-Resolution Timer

A counter is a general term used in programming to refer to an incrementing variable. Some systems include a high-resolution performance counter that provides high-resolution elapsed times.

If a high-resolution performance counter exists on the system, you can use the QueryPerformanceFrequency function to express the frequency, in counts per second. The value of the count is processor dependent. On some processors, for example, the count might be the cycle rate of the processor clock.

The QueryPerformanceCounter function retrieves the current value of the high-resolution performance counter. By calling this function at the beginning and end of a section of code, an application essentially uses the counter as a high-resolution timer. For example, suppose that QueryPerformanceFrequency indicates that the frequency of the high-resolution performance counter is 50,000 counts per second. If the application calls QueryPerformanceCounter immediately before and immediately after the section of code to be timed, the counter values might be 1500 counts and 3500 counts, respectively. These values would indicate that .04 seconds (2000 counts) elapsed while the code executed.

查看更多
做自己的国王
7楼-- · 2019-01-22 02:20

Both will likely fit your needs just fine, but I would say use StopWatch. Why? Cause it's meant for the task you're doing.

You've got one class that's built to return the current date/time, which as it happens can be used for timing things, and you've got one class specifically designed for timing things.

In this case the differences only really exist if you need millisecond accuracy (In which case StopWatch is more accurate), but as a general principal if a tool exists specifically for the task you're looking for then it's the better one to use.

查看更多
登录 后发表回答