Is DateTime.Now the best way to measure a function's performance?

70,268

Solution 1

No, it's not. Use the Stopwatch (in System.Diagnostics)

Stopwatch sw = Stopwatch.StartNew();
PerformWork();
sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);

Stopwatch automatically checks for the existence of high-precision timers.

It is worth mentioning that DateTime.Now often is quite a bit slower than DateTime.UtcNow due to the work that has to be done with timezones, DST and such.

DateTime.UtcNow typically has a resolution of 15 ms. See John Chapman's blog post about DateTime.Now precision for a great summary.

Interesting trivia: The stopwatch falls back on DateTime.UtcNow if your hardware doesn't support a high frequency counter. You can check to see if Stopwatch uses hardware to achieve high precision by looking at the static field Stopwatch.IsHighResolution.

Solution 2

If you want something quick and dirty I would suggest using Stopwatch instead for a greater degree of precision.

Stopwatch sw = new Stopwatch();
sw.Start();
// Do Work
sw.Stop();

Console.WriteLine("Elapsed time: {0}", sw.Elapsed.TotalMilliseconds);

Alternatively, if you need something a little more sophisticated you should probably consider using a 3rd party profiler such as ANTS.

Solution 3

This article says that first of all you need to compare three alternatives, Stopwatch, DateTime.Now AND DateTime.UtcNow.

It also shows that in some cases (when performance counter doesn't exist) Stopwatch is using DateTime.UtcNow + some extra processing. Because of that it's obvious that in that case DateTime.UtcNow is the best option (because other use it + some processing)

However, as it turns out, the counter almost always exists - see Explanation about high-resolution performance counter and its existence related to .NET Stopwatch?.

Here is a performance graph. Notice how low performance cost UtcNow has compared to alternatives:

Enter image description here

The X axis is sample data size, and the Y axis is the relative time of the example.

One thing Stopwatch is better at is that it provides higher resolution time measurements. Another is its more OO nature. However, creating an OO wrapper around UtcNow can't be hard.

Solution 4

It's useful to push your benchmarking code into a utility class/method. The StopWatch class does not need to be Disposed or Stopped on error. So, the simplest code to time some action is

public partial class With
{
    public static long Benchmark(Action action)
    {
        var stopwatch = Stopwatch.StartNew();
        action();
        stopwatch.Stop();
        return stopwatch.ElapsedMilliseconds;
    }
}

Sample calling code

public void Execute(Action action)
{
    var time = With.Benchmark(action);
    log.DebugFormat(“Did action in {0} ms.”, time);
}

Here is the extension method version

public static class Extensions
{
    public static long Benchmark(this Action action)
    {
        return With.Benchmark(action);
    }
}

And sample calling code

public void Execute(Action action)
{
    var time = action.Benchmark()
    log.DebugFormat(“Did action in {0} ms.”, time);
}

Solution 5

The stopwatch functionality would be better (higher precision). I'd also recommend just downloading one of the popular profilers, though (DotTrace and ANTS are the ones I've used the most... the free trial for DotTrace is fully functional and doesn't nag like some of the others).

Share:
70,268
David Basarab
Author by

David Basarab

David Basarab Software craftsman that is constantly scrubbing my code.

Updated on October 22, 2020

Comments

  • David Basarab
    David Basarab over 3 years

    I need to find a bottleneck and need to accurately as possible measure time.

    Is the following code snippet the best way to measure the performance?

    DateTime startTime = DateTime.Now;
    
    // Some execution process
    
    DateTime endTime = DateTime.Now;
    TimeSpan totalTimeTaken = endTime.Subtract(startTime);
    
  • Aditya Sinha
    Aditya Sinha over 13 years
    What about better granularity? Many things happen in less than one ms.
  • Anthony Mastrean
    Anthony Mastrean over 13 years
    Return the Elapsed property then, it's a TimeSpan. I'm just showing you the pattern. Have fun implementing it.
  • DiVan
    DiVan almost 13 years
    I'd place one PerformWork(); before Stopwatch for "heating up".
  • devgeezer
    devgeezer about 12 years
    Must also add recommendation that if your PerformWork() is very short that you may be able to call it repeatedly and compute the average of the batch of calls. Also, time an entire batch of calls rather than starting/stopping your Stopwatch to avoid a strobe-effect that will muddy your timing measurements.
  • Pavel Savara
    Pavel Savara almost 12 years
    Stopwatch is not threadsafe on multicore. See stackoverflow.com/questions/6664538/… and stackoverflow.com/questions/1149485/…
  • Peter Mortensen
    Peter Mortensen about 11 years
    The first link appears to be broken.
  • Valentin Kuzub
    Valentin Kuzub about 11 years
    became broken yep.. time machine can show it I would guess. Btw why you edit "the three" , the isn't needed here I believe.
  • nawfal
    nawfal about 11 years
    Return Elapsed.TotalMilliseconds for higher precision. See this question too stackoverflow.com/questions/8894425/…
  • Flappy
    Flappy about 10 years
    sw.ElapsedMilliseconds; can also
  • Adrian Ratnapala
    Adrian Ratnapala over 9 years
    I thought a typical Windows machine kept its hardware clock in local time and then had to look up the timezone when converting to UTC. (A crazy system I know, but Dos 5.2 and Win3.1 were crazy beasts).
  • Kyborek
    Kyborek about 9 years
    a little bit to add using System.Diagnostics;
  • Ron
    Ron almost 9 years
    @Pavel, to be clear, Stopwatch is recommended by Microsoft as the best solution (low overhead and high precision) on modern multicore processors that are running Windows 7 and Windows 8. msdn.microsoft.com/en-us/library/windows/desktop/…
  • user2864740
    user2864740 almost 7 years
    "Windows has and will continue to invest in providing a reliable and efficient performance counter. When you need time stamps with a resolution of 1 microsecond or better and you don't need the time stamps to be synchronized to an external time reference, choose QueryPerformanceCounter.." (Stopwatch uses QPC)