106

I wanted to track the performance of my code so I stored the start and end time using System.DateTime.Now. I took the difference between the two as the time my code to execute.

I noticed though that the difference didn't appear to be accurate. So I tried using a Stopwatch object. This turned out to be much, much more accurate.

Can anyone tell me why Stopwatch would be more accurate than calculating the difference between a start and end time using System.DateTime.Now?

BTW, I'm not talking about a tenths of a percent. I get about a 15-20% difference.

Superbest
  • 25,318
  • 14
  • 62
  • 134
Randy Minder
  • 47,200
  • 49
  • 204
  • 358
  • 2
    Based on your comment to Kelsey's answer, I'd be interested in seeing the code that records the start and stop times. A difference of 11 seconds (huge) is nothing to do with the accuracy differences of the two classes, so something else has to be going on. – Igby Largeman May 27 '10 at 17:32
  • 3
    Also, if you're only interested in the `TimeSpan` between two dates, it's usually better to use `DateTime.UtcNow` instead of `DateTime.Now`, since you usually don't want daylight time shifts and other local time variations to influence the result. – Daniel Pryden May 27 '10 at 17:57
  • @DanielPryden, See [The Case Against DateTime.Now](http://codeofmatt.com/2013/04/25/the-case-against-datetime-now/), which makes that point exactly. +1 – Matt Johnson-Pint Sep 06 '13 at 01:58

3 Answers3

87

As per MSDN:

The Stopwatch measures elapsed time by counting timer ticks in the underlying timer mechanism. If the installed hardware and operating system support a high-resolution performance counter, then the Stopwatch class uses that counter to measure elapsed time. Otherwise, the Stopwatch class uses the system timer to measure elapsed time. Use the Frequency and IsHighResolution fields to determine the precision and resolution of the Stopwatch timing implementation.

It uses a higher resolution / precision than DateTime.Now.

You can also check out these related links:

Environment.TickCount vs DateTime.Now

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

DateTime is good enough for precision to the second probably but anything beyond that I would recommend StopWatch.

Community
  • 1
  • 1
Kelsey
  • 47,246
  • 16
  • 124
  • 162
37

It's better to use the Stopwatch class because it's much more accurate than subtracting DateTime values:

Stopwatch s = Stopwatch.StartNew();
// Tested code here
s.Stop();
Console.WriteLine("Elapsed Time: {0} ms", s.ElapsedMilliseconds);

Unfortunately, this simple piece of code won't be enough to get accurate measurements most of the times because there’s a lot of activity going on under the hood of the OS, which can steal some CPU time and slow down the execution of your code. That’s why it is best to execute the tests multiple times and then remove the lowest and the highest times. For that puprose it is a good solution to have a method that executes the tested code multiple times, removes the lowest and the greatest times and calculates the average time. I have published a sample testing method in my blog.

Pavel Vladov
  • 4,707
  • 3
  • 35
  • 39
  • I checked your blog's link. There is a slight error in the calculation of the average timing. Instead of `double averageTime = ((double)totalTime) / (count - discardCount);` it should be `double averageTime = ((double)totalTime) / (count - (2*discardCount));`. No? – displayName Aug 06 '15 at 13:50
  • Hi, **no it shouldn't, the code in the blog is correct**. Please take a look at the line, where `count` is defined. It is defined as: `int count = repetitions - discardCount;`. That is why when calculating the average time I subtract `discardCount` only once (it has already been subtracted once). Regards. – Pavel Vladov Aug 10 '15 at 05:53
  • That's correct. Didn't pay attention to it. You are right. – displayName Aug 10 '15 at 12:34
  • It's worth mentioning that another way to measure time is to just pick the top X of N runs. Like run it 5 times and use the best one. This is the one that will have the least OS interference after all. There's pros and cons to both approaches however – mirhagk Jan 02 '17 at 23:06
9

this timing function performance link discusses your exact problem, specifically this paragraph:

The problem is that according to MSDN the resolution of the DateTime.Now function is 10+ milliseconds, and we need to call it twice! So that would introduce a 20+ ms swing in your runtime measurement. As our function calls are often likely to be a lot quicker to return than this 20ms window this isn’t good enough.

EDIT: It kind of sounds like the second DateTime.Now is being called at a different time than when the stopwatch method concludes.

Robb
  • 2,666
  • 4
  • 20
  • 24
  • Here: https://blogs.msdn.microsoft.com/ericlippert/2010/04/08/precision-and-accuracy-of-datetime/ ; Eric Lippert has a nice explanation about how much precission it has. 1/64 of a second at best. Two calls one at the beginning and at the end, then you have 1/32 of a second as precission, which might be up to ~31 ms sway. – Ünsal Ersöz Jun 26 '19 at 11:16