高精度计时器 ![高精度计时器 - 秒大刀 - 秒大刀的城堡](http://img617.ph.126.net/9NmBwkKNPXi9NZm4cKV28A==/1662109737478466930.jpg)
以前写游戏时习惯用
QueryPerformanceFrequency和
QueryPerformanceCounter来做高精度计时器。DirectX SDK自带的DXUT中有个CDXUTTimer就是这么用的。很多应用都会建立在高精度计时器上,计时器的精度可以在一定程度上影响游戏帧率的准确、稳定。
但要注意QueryPerformanceFrequency函数在多核CPU上是有猫腻的:
On a multiprocessor computer, it should not matter which processor is called. However, you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL). To specify processor affinity for a thread, use the
SetThreadAffinityMask function. (
MSDN)
QPF还可能面临向前回退的问题(
Performance counter value may unexpectedly leap forward),而且在一些操作系统上也可能表现很差(
Programs that use the QueryPerformanceCounter function may perform poorly in Windows Server 2000, in Windows Server 2003, and in Windows XP)。这些无疑给了接口优美貌似好用的QPF当头一棒——停!
我自己的AMD双核CPU在QueryPerformanceCounter函数实现上就
存在上述的BUG!只有打了“
AMD dual core optimizer”补丁后才能正常工作。
游戏在部署时一般采用无需管理员权限的xcopy方式,所以不能保证玩家机器上打过该补丁,帮用户安装还会遇到权限问题。
timeGetTime是Windows Multimedia中获取高精度时间的另外一种方式。在NT和2000系统以后,该方法默认精度为5ms,通过
timeBeginPeriod和
timeEndPeriod可以将精度调整到1ms。
那为什么timeGetTime精度上只能达到1ms呢?
“ 最初设计IBM-PC的时候,主板上用了一个14.31818MHz的晶振,这是当时PC上最高的时钟频率了。 这个晶振经过12分频后作为定时器/计数器的输入,就是1.1931816MHz。为了保持兼容,这个1.1931816MHz是一直存在的,直到现在的主板也是如此(不管它是如何产生的),那个14.31818倒是不一定存在了。 这就是为什么QueryPerformanceFrequency通常会返回1193182这个数字的原因。 在这个频率下,计时的最高精度是834ns”(CSDN)
结论:
暂时放弃QueryPerformanceFrequency方式。
RDTSC指令比较高深,暂时还不敢用,我想也不至于用。
先选定timeGetTime的1ms精度计时器。