Windows timer high resolution
I synchronized the performance counter value to the corresponding system time by repeatedly spinning inside a tight loop, waiting for the system time to change. When the system time changed, I stored the counter value together with the system time. Take a look at the results:. Let's look at some possible improvements for all of these problems in the following sections. The problem with the synchronization implementation is that it didn't take into account the preemptiveness of the Windows NT scheduler.
There is no guarantee, for example, that a thread context switch won't take place between the following two lines of code, resulting in a delay of an unknown period of time:. The simplistic synchronization function will still succeed most of the time when executing under the following circumstances:.
Unfortunately, there isn't much you can do about the hardware interrupts, but well-behaving drivers should handle their interrupts, queue a deferred procedure call DPC and even process the DPC within an order of microseconds. The problem is that you can't be sure that all drivers in your system are actually well behaved. In fact, even if you only have conforming drivers in your system, you might still have a lot of interrupts.
Nevertheless, there is a reliable way of synchronizing without necessarily raising the process and thread priorities. Figure 3 shows a basic flowchart of the steps involved. The big difference from the previous implementation is that you now also use the performance counter itself to verify that you're keeping within the desired accuracy level. This sounds simple enough, but a closer examination of Figure 3 will show you that it isn't quite as simple as it seems.
The reason for this is that from the point the system time is stored in t1 to the point the counter value is stored in p1, the system time could potentially change without being detected until the next run through the inner loop. Following that, you could erroneously assume that the time changed somewhere in between the latest two counter values, when in fact it did not.
To safeguard against this, you should assume that the system time changed either between the latest or the previous two counter values except for the unlikely event that it should change the very first time through the inner loop. At the end of the synchronization, an adjustment of the counter value is performed; this is to make sure that the returned value is within the desired accuracy.
Figure 4 shows this process. This method of synchronization needs quite a few iterations to complete, but in practice that hasn't proven to be a problem. For further information on synchronizations and their accuracy, you should take a look at the sidebar "Synchronization: How Good Can it Get?
Although I've managed to get a good starting point, there are still some problems to be addressed. Suppose you perform this synchronization at some distinct point in time. As shown earlier, the frequency reported by QueryPerformanceCounter is used for calculating the current system time with a high resolution. This is because the performance counter is not intended to be used for measuring extended periods of time. I ran a small test to find out how much of an effect this would have, using two microseconds as the acceptable synchronization limit.
The results are shown in Figure 5. As it turns out, my high-resolution clock had deviated from the real system time by a millisecond after only seconds. A quick calculation indicates that this corresponds to an error in the reported performance counter frequency of roughly 9 parts per million PPM.
An error of 0. Initially, I considered two options. First, the user is responsible for periodical resynchronization, and thus must also determine how often this must be done. Second, the synchronization is performed by a background thread every nth second.
Even before testing the first option, I decided against it. The second option seemed more viable and the only problem I could foresee was that the required synchronization between the clients and the synchronization thread would incur some overhead. The ease of use still outweighs the increased complexity and overhead. The sample implementation provided in the download uses a background thread to synchronize the performance counter to the system time. Synchronization: How Good Can it Get?
Using the method of synchronization I describe in this article, you can specify the accuracy of the results you want. In reality, however, there is a platform-dependent hardware and software limit on the quality of the results you can achieve. The clock interrupt handler in Windows NT takes some time to execute, effectively limiting your precision to no better than the clock interrupt handler's execution time, plus the time spent in thread context switching, plus the execution times for the function calls needed to check when the time has changed.
If you are running on a symmetric multiprocessing SMP machine, you can avoid clock interrupt problems by running the synchronization thread on another CPU. Prohibiting the synchronization thread from running on the CPU that handles the clock interrupt can make an almost tenfold difference in the synchronization accuracy on an SMP machine. The only problem is that you first need to know which CPU actually handles the clock interrupt. I can only tell from my limited experience that it seems to be handled by CPU 0 which makes some kind of weird sense, I suppose.
You should just make sure that the process is allowed to run on the other processors by checking the results from calling GetProcessAffinityMask beforehand. The graph in Figure 6 displays the high-resolution time deviation from system time over a period of some 13 minutes.
However, high-resolution timers require system clock interrupts to—at least, temporarily—occur at a higher rate, which tends to increase power consumption. Thus, drivers should use high-resolution timers only when timer accuracy is essential, and use default-resolution timers in all other cases.
When the driver calls the ExSetTimer routine to set the high-resolution timer, the operating system increases the resolution of the system clock, as necessary, so that the times at which the timer expires more precisely correspond to the nominal expiration times specified in the DueTime and Period parameters.
This member is a part of the structure starting with Windows 8. For example, for Windows running on an x86 processor, the default interval between system clock ticks is typically about 15 milliseconds, and the minimum interval between system clock ticks is about 1 millisecond.
If a driver specifies a relative expiration time for a default-resolution timer, the timer can expire up to about 15 milliseconds earlier or later than the specified expiration time. If a driver specifies a relative expiration time for a high-resolution timer, the timer can expire as late as about a millisecond after the specified expiration time but it never expires early. For more information about the relationship between system clock resolution and timer accuracy, see Timer Accuracy. If no high-resolution timers are set, the operating system typically runs the system clock at its default rate.
However, if one or more high-resolution timers are set, the operating system might need to run the system clock at its maximum rate for at least a part of the time before these timers expire. To avoid unnecessarily increasing power consumption, the operating system runs the system clock at its maximum rate only when necessary to satisfy the timing requirements of high-resolution timers. For example, if a high-resolution timer is periodic, and its period spans several default system clock ticks, the operating system might run the system clock at its maximum rate only in the part of the timer period that immediately precedes each expiration.
For the rest of the timer period, the system clock runs at its default rate. To prevent excessive power consumption, drivers should avoid setting the period of a long-running high-resolution timer to a value that is less than the default interval between system clock ticks. Stopwatch class also provides several convenient methods to perform time-interval measurements. The Windows kernel provides kernel-mode access to the performance counter through KeQueryPerformanceCounter from which both the performance counter and performance frequency can be obtained.
KeQueryPerformanceCounter is available from kernel mode only and is provided for writers of device drivers and other kernel-mode components. Can it be synchronized to an external epoch such as UTC? QPC is based on a hardware counter that can't be synchronized to an external time reference, such as UTC. Is QPC affected by daylight savings time, leap seconds, time zones, or system time changes made by the administrator?
Is QPC accuracy affected by processor frequency changes caused by power management or Turbo Boost technology? If the processor doesn't have an invariant TSC, QPC will revert to a platform hardware timer that won't be affected by processor frequency changes or Turbo Boost technology. Does QPC reliably work on multi-processor systems, multi-core system, and systems with hyper-threading? How do I determine and validate that QPC works on my machine? Which processors have non-invariant TSCs? How can I check if my system has a non-invariant TSC?
You don't need to perform this check yourself. Windows operating systems perform several checks at system initialization to determine if the TSC is suitable as a basis for QPC. However, for reference purposes, you can determine whether your processor has an invariant TSC by using one of these:. An asterisk means "True". How often does QPC roll over? Not less than years from the most recent system boot, and potentially longer based on the underlying hardware timer used.
For most applications, rollover isn't a concern. What is the computational cost of calling QPC? The computational calling cost of QPC is determined primarily by the underlying hardware platform. If the TSC can't be used, the system will select a different hardware time basis.
This cost is dominated by the time required to access the hardware device on the motherboard. Does QPC require a kernel transition system call? Is the performance counter monotonic non-decreasing? Can the performance counter be used to order events in time? How accurate is the performance counter? The answer depends on a variety of factors.
For more info, see Low-level hardware clock characteristics. I need to convert the QPC output to milliseconds.
How can I avoid loss of precision with converting to double or float? There are several things to keep in mind when performing calculations on integer performance counters:. As a general principle, delay these computations and conversions as long as possible to avoid compounding the errors introduced.
A file time is a bit value that represents the number of nanosecond intervals that have elapsed since A. Conversion between the two requires calculating the ratio of the QPC interval and nanoseconds intervals.
Be careful to avoid losing precision because the values might be small 0. Why is the time stamp that is returned from QPC a signed integer? Calculations that involve QPC time stamps might involve subtraction. By using a signed value, you can handle calculations that might yield negative values. How can I obtain high resolution time stamps from managed code?
Call the Stopwatch. GetTimeStamp method from the System. For an example about how to use Stopwatch. GetTimeStamp , see Acquiring high resolution time stamps from managed code.
Do I need to set the thread affinity to a single core to use QPC? For more info, see Guidance for acquiring time stamps. This scenario is neither necessary nor desirable.
Performing this scenario might adversely affect your application's performance by restricting processing to one core or by creating a bottleneck on a single core if multiple threads set their affinity to the same core when calling QueryPerformanceCounter. Absolute clocks provide accurate time-of-day readings. They are typically based on Coordinated Universal Time UTC and consequently their accuracy depends in part on how well they are synchronized to an external time reference.
Difference clocks measure time intervals and aren't typically based on an external time epoch. QPC is a difference clock and isn't synchronized to an external time epoch or reference. When you use QPC for time-interval measurements, you typically get better accuracy than you would get by using time stamps that are derived from an absolute clock. This is because the process of synchronizing the time of an absolute clock can introduce phase and frequency shifts that increase the uncertainty of short term time-interval measurements.
QPC uses a hardware counter as its basis. Hardware timers consist of three parts: a tick generator, a counter that counts the ticks, and a means of retrieving the counter value.
The characteristics of these three components determine the resolution, precision, accuracy, and stability of QPC. If a hardware generator provides ticks at a constant rate, time intervals can be measured by simply counting these ticks.
The rate at which the ticks are generated is called the frequency and expressed in Hertz Hz. The reciprocal of the frequency is called the period or tick interval and is expressed in an appropriate International System of Units SI time unit for example, second, millisecond, microsecond, or nanosecond. The resolution of the timer is equal to the period. Resolution determines the ability to distinguish between any two time stamps and places a lower bound on the smallest time intervals that can be measured.
0コメント