44

I need to time the execution of a code sequence written in C#. Using DateTime.Now I get incorrect values for the millisecond field. For example:

 int start_time, elapsed_time;

 start_time = DateTime.Now.Millisecond;

 for(int i = 0; i < N_ITER; i++) {
       // cpu intensive sequence
 }

 elapsed_time = DateTime.Now.Millisecond - start_time;

elapsed_time gives negative values.

How may I replace DateTime in order to obtain the actual value of the elapsed time?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Sebi
  • 4,262
  • 13
  • 60
  • 116
  • 10
    `System.Diagnostics.Stopwatch` ??? – L.B Nov 27 '12 at 17:36
  • 5
    Sure it will give you sometimes a minus value You are not taking the timestamp, you are taking only a portion of it only. Explanation: DateTime.Now.Second = 50 After 15 Seconds DateTime.Now.Second will be 5, not 65 Thats why you are getting the negative values. This applies to Hours, minutes, seconds, milliseconds So best thing to do is, either a stop watch, or two DateTime instances, one for start and one for end, var st =DateTime.Now Console.Write((DateTime.Now - st).ToString()) – sameh.q May 30 '13 at 06:16
  • Possible duplicate of [Measuring code execution time](https://stackoverflow.com/questions/16376191/measuring-code-execution-time) – Michael Freidgeim Jun 19 '17 at 03:30

7 Answers7

116
using System.Diagnostics;

//...

var stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < N_ITER; i++) {
    // cpu intensive sequence
}
stopwatch.Stop();
elapsed_time = stopwatch.ElapsedMilliseconds;
RavingDev
  • 2,817
  • 1
  • 17
  • 19
15

Answer EDITED based on comments

This answer is only trying to count the total elapsed Milliseconds between two times, where the times are derived directly from DateTime.Now. As per the conversation, it's understood that DateTime.Now is vulnerable to outside influences. Hence the best solution would be to use the Stopwatch class. Here's a link that better explains (IMO) and discusses the performance between DateTimeNow, DateTime.Ticks, StopWatch.

Original Answer

The way you cast it into a int is the issue. You need better casting and extra elements :) This may looks simple compared to an efficient timer. But it works:

DateTime startTime, endTime;
startTime = DateTime.Now;

//do your work

endTime = DateTime.Now;
Double elapsedMillisecs = ((TimeSpan)(endTime - startTime)).TotalMilliseconds;

There is a reference on the web, you may want to check out as well.

Community
  • 1
  • 1
bonCodigo
  • 14,268
  • 1
  • 48
  • 91
  • but DateTime.Now.Millisecond returns an int – Sebi Nov 27 '12 at 17:38
  • 1
    That has nothing to do with the issue. `DateTime.Now` returns the system time as a file time, which can vary a bit for any of a dozen reasons. `Stopwatch` laboriously sets how many system ticks elapse per second/millisecond/etc and basically sets up its own environment to do the measurement. This is exactly what you *need* to do when benchmarking things like this, so it is *repeatable*. – tmesser Nov 27 '12 at 17:46
  • I was about to ask about the differences between them, so thanks – Sebi Nov 27 '12 at 17:48
  • You guys are too fast to comment while I have been writing my answer. :) Take a look at the complete answer please. – bonCodigo Nov 27 '12 at 17:52
  • @YYY Since someone has downvoted me and my answer works, I was curious to research. And I found out some great sources/proofs. :) Check this [link](http://stackoverflow.com/questions/1487146/convert-difference-between-2-times-into-milliseconds). It has answers that are similar to mine. – bonCodigo Nov 27 '12 at 18:45
  • @bonCodigo The link you provided is a completely different application, if for no other reason than *it's a web/forms application, not a benchmarking application.* I didn't downvote you, but whoever did was fully justified because you are using the wrong tool for the job at hand. If you would like to dispute the point, you should start with showing that `DateTime.Now` cannot be influenced by outside factors. Considering that it pulls its values *specifically from* an outside resource, I think you'll find this difficult. – tmesser Nov 27 '12 at 18:50
  • If we breakdown OP's main intention, that he wants to find out the total elapsed time in milliseconds between a start time and an end time. So I provided the answer according to that, and it works. **HOWEVER** , when I understand that " the solution should be independent of any influences on DATETIME.NOW " ---> that clearly means my answer can't be used. So I will put a note on the answer in that case. But again as for the logic, this does the job of finding elapsed time in milliseconds between two times IGNORING any influence on DateTime.Now – bonCodigo Nov 27 '12 at 19:04
  • I don't think the `(TimeSpan)` cast does anything – clamchoda Oct 20 '22 at 20:18
6

You're looking for the Stopwatch class. It is specifically designed to bring back high-accuracy time measurements.

var stopwatch = new Stopwatch();

stopwatch.Start();
for (int i = 0; i < N_ITER; i++)
{
     // cpu intensive sequence
}
stopwatch.Stop();

var elapsed = stopwatch.ElapsedMilliseconds;
tmesser
  • 7,558
  • 2
  • 26
  • 38
3

Stopwatch there are examples in the URL
https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.stopwatch?view=netframework-4.8

using System.Diagnostics;
//...
Stopwatch watch = new Stopwatch();
watch.Start();
// here the complex program. 
//...
watch.Stop();
TimeSpan timeSpan = watch.Elapsed;
Console.WriteLine("Time: {0}h {1}m {2}s {3}ms", timeSpan.Hours, timeSpan.Minutes, 
timeSpan.Seconds, timeSpan.Milliseconds);
Valentin Petkov
  • 1,570
  • 18
  • 23
2

DateTime.Millisecond just returns the millisecond fraction of the second, from 0-999. You would need to take the rest of the datetime into consideration when doing timings.

However, you should look at using the StopWatch class for these kinds of performance timings.

StuartLC
  • 104,537
  • 17
  • 209
  • 285
1

This works for me:

var lapsedTime = DateTime.Now.Subtract(beginTime).TotalMilliseconds;
4b0
  • 21,981
  • 30
  • 95
  • 142
Clive
  • 31
  • 1
  • 3
0

Here is what I used to obtain the time for a simple computation:

class Program
{
    static void Main(string[] args)
    {
        Decimal p = 0.00001m;
        Decimal i = 0m;
        DateTime start = new DateTime();
        DateTime stop = new DateTime();

        for (i = p; i <= 5; i = i + p)
        {
            Console.WriteLine("result is: " + i);
            if (i==p) start = DateTime.Now;
            if (i==5) stop = DateTime.Now;
        }

        Console.WriteLine("Time to compute: " + (stop-start));

    }
}