Measure execution time in C#
Asked Answered
S

8

39

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?

Shearwater answered 11/10, 2010 at 2:42 Comment(0)
V
29

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.

Villareal answered 11/10, 2010 at 2:49 Comment(3)
Stopwatch also uses the high resolution timer (when it is available), which is essential when measuring code with short execution times.Elbow
@Kragen - that is what I meant about the underlying timer. I will clarify by reference to the Win32 APIs.Villareal
Please note that it's Stopwatch and not StopWatch (minor, I know, but autoresolving dependencies won't work if you get it wrong).Unwrap
C
13

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!

Cimmerian answered 11/10, 2010 at 2:58 Comment(0)
M
6

Neither will hurt the performance, because you say it is not that critical. StopWatch seems more appropriate - you are only subtracting time from time and not one date from another. Date stuff takes a tad more memory and CPU time to deal with. There are also ways to make the code cleaner, in case you plan on reusing it in several places. Overloading using comes to mind. I will search for an example. Ok, code stolen from:

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);
    }
}
Menes answered 11/10, 2010 at 2:46 Comment(1)
I don't think it takes more time. I think it just is less accurate since it isn't made for this kind of measurement.Respondence
L
6

I generally use StopWatch for this kind of situation.

From MSDN page:

StopWatch

Provides a set of methods and properties that you can use to accurately measure elapsed time.

In the following post I use it to compare the execution time of LINQ vs PLINQ:

Parallel LINQ (PLINQ) with Visual Studio 2010

Lopes answered 11/10, 2010 at 2:47 Comment(1)
+1 for link to MSDN where I found that it looks like the name has been changed from StopWatch to StopwatchBoschbok
I
1

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.

Imperception answered 11/10, 2010 at 2:58 Comment(0)
T
1

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));
Thistly answered 11/10, 2010 at 6:12 Comment(0)
E
0

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();
Eggcup answered 16/3, 2012 at 16:33 Comment(0)
K
0

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

}
Karolynkaron answered 12/10, 2013 at 0:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.