Reputation: 321
I often use System.Diagnostics.Stopwatch to measure how long time the execution of a code takes. The documentation says that it should be quite exact. I believed that the measured time can differ from the truth only by time which was used to start and stop the Stopwatch.
I estimated how big this error could be by following code:
var sw = new Stopwatch();
sw.Start();
sw.Stop();
It measured: 00:00:00.0000090. Wow. The error is under 10us.
Now after years I started to be curious about Stopwatch again. Is it really so exact? Does it measure wall clock time? Or where is definition of what exactly it measures? What if the process is blocked by IO operation? Is it still so exact?
I did small benchmark again:
var sw = new Stopwatch();
var startTime = System.DateTime.Now;
sw.Start();
for (int i = 0; i < 1000; i++) {
Console.WriteLine(i);
Console.Error.WriteLine(i);
}
var endTime = System.DateTime.Now;
sw.Stop();
Console.Error.WriteLine(
@"The application was running {0}, but the stopwatch measured {1}.",
endTime - startTime,
sw.Elapsed
);
When I started the application normally the output was:
The application was running 00:00:01.5740900, but the stopwatch measured 00:00:01.5732109. The difference is almost 1ms.
When I pipe standard output of the application to the process which waits some time before reading its input I get following result:
The application was running 00:04:51.2076561, but the stopwatch measured 00:04:51.2012677.
The difference is more than 6ms.
What is happening? Is the Stopwatch inaccurate? Or do I just misinterpret what is and what isn't measured?
Edit: I know that System.DateTime.Now has lower resolution, but would expect that the difference would be in ms.
Upvotes: 3
Views: 1770
Reputation: 68750
The Stopwatch
is fine, it's the endTime - startTime
that's wrong.
DateTime.Now
has lower resolution that a stopwatch.
From MSDN:
The Now property is frequently used to measure performance. However, because of its low resolution, it is not suitable for use as a benchmarking tool. A better alternative is to use the Stopwatch class.
Upvotes: 6
Reputation: 172618
I think you dont need to rely on single measurement. You need to run the check several times(may be 20 to 50 times) and then take the average.
Also to note that StopWatch is a shell over QueryPerformanceCounter functionality.
You can for example check this article: Performance Tests: Precise Run Time Measurements with System.Diagnostics.Stopwatch
Upvotes: 6