Some time ago, I noted that There is a std::
, but no low_
.
The Visual C++ library treats std::
as an alias for std::
, which uses QueryÂPerformanceÂCounter()
to retrieve the current time, and the multiplies it by the reciprocal of QueryÂPerformanceÂFrequency()
to convert it to a clock tick count. So you are paying for a multiplication after QueryÂPerformanceÂCounter()
returns.
But there’s a lot going on inside QueryÂPerformanceÂCounter()
itself, too. It has to use a different algorithm depending on things like whether the timestamp counter (such as RDTSC
on x86 or CNTVCT_EL0
on AArch64) is reliable, whether the system is running inside a virtual machine, whether the process is running under emulation, and various other conditions. In the worst case, it needs to make a system call into the kernel.
On the other hand, GetÂTickÂCount64()
merely reads two 64-bit values from memory and multiplies them. One is a raw value that is updated by the kernel at each system timer interrupt (worst case), and the other is a conversion factor calculated at system startup to convert the raw value into milliseconds.
These two 64-bit values come from a special page that is mapped into user mode from kernel mode that contains handy values, including the current tick count. As it turns out, this is significantly faster than going through all the logic of QueryÂPerformanceÂCounter
. It’s a great choice if you do not need high resolution.
And deciding how long to sleep a thread is a case where you do not need high resolution. Most of the functions for sleeping a thread already operate in milliseconds, so getting the value in milliseconds saves you a lot of conversions. Calculating values with sub-millisecond accuracy is pointless if the result is going to be converted to milliseconds anyway. And the accuracy of most (all?) of these sleep functions is only as good as the system timer anyway, so really they are good to only 10 or 50 milliseconds.¹
It’s like doing precise calculations to determine that you need to set your phone alarm to wake you in exactly 32 minutes, 21.1315 seconds. Your phone alarm can’t wake you to sub-second resolution, so all that work to calculate those extra .1315 seconds was wasted.
Now, I didn’t know all of these details when I originally wrote that article. But it stands to reason that GetÂTickÂCount64
is a lot cheaper than QueryÂPerformanceÂCounter
because GetÂTickÂCount64
asks for less. Even if GetÂTickÂCount64
ends up not being faster than QueryÂPerformanceÂCounter
, it surely won’t be slower.
¹ Or one millisecond if your process has called timeBeginPeriod(1)
to ask that the system timer be sped up to 1 millisecond.
0 comments
Be the first to start the discussion.