Inside the static Stopwatch
constructor we can see the following code, that basicly checks whether a high-resolution performance counter exists.
static Stopwatch()
{
if (!SafeNativeMethods.QueryPerformanceFrequency(out Frequency))
{
IsHighResolution = false;
Frequency = 0x989680L;
tickFrequency = 1.0;
}
else
{
IsHighResolution = true;
tickFrequency = 10000000.0;
tickFrequency /= (double) Frequency;
}
}
On MSDN it says about QueryPerformanceFrequency
:
Retrieves the frequency of the high-resolution performance counter, if one exists
It's pretty unclear, however, when exactly does it exist? I suspect it usually exists on current machines, but when exactly doesn't it?
It's interesting because when it doesn't exist, Stopwatch
becomes a mere wrapper around the DateTime.UtcNow
property.
Actual resolution of the system time is on the order of milliseconds (even though it is claimed to be 1/10th of a millisecond, I've never seen a workstation that provides that resolution reliably).
However, you can use additional hardware (like time code readers) which provides resolutions down to nanoseconds. These are usually used in industrial control systems in line with IPCs (industrial PCs) to synchronize DAQ hardware. You can see an example with 100 ns resolution in PCI Express Slot Cards. Time code processor for PCI express low-profile x1 local bus.
Ordinary workstations will almost always use high-resolution counters, but actually resolution will not be what you would expect (micro or nano seconds) without additional hardware.
There is a difference between a timer and a stopwatch, and confusing the two leads to erroneous assumptions. Unfortunately, the term timer is used to mean multiple things all too often.
Any machine that runs Windows 2000 or later likely has a high frequency timer. I have never run across a computer that runs Windows 2000 later that does not have such a thing.
Now, that's the high frequency timer. There are also timers: Windows or .NET components. These timers are not used for keeping time or for measuring time, but rather for performing actions at periodic intervals. The Windows timer objects are capable of 1 ms resolution, and are very reliable when the computer is not involved in CPU intensive operations. The .NET timer objects are limited to approximately 15 ms resolution. You can get around that by using P/Invoke to interact directly with the Windows objects, but it's not often necessary.
The .NET Stopwatch class is based on the high frequency timer. In general,
Start
queries the performance counter and stores the value. When youStop
, it queries the performance counter again. The elapsed time is a simple subtraction of those two values. You can get better than microsecond resolution from the Stopwatch.And in fact, you can use a
Stopwatch
with a busy-waiting loop that gives you sub-millisecond resolution. I doubt that you could get sub-microsecond resolution with it.The important thing to understand is that, although timers aren't reliable beyond 1 millisecond, the stopwatch, which measures elapsed time, is much more precise. You can probably trust microsecond-level elapsed time measurements from Stopwatch. Beyond that, I wouldn't count on it.