根据MSDN文章Game Timing and Multicore Processors, QueryPerformanceFrequency()和QueryPerformanceCounter()函数被认为是最好的。 但是在不支持的情况下,我可以使用timeGetTime()或GetTickCount()。
但是你不一定要问正确的问题
窗口上常用的四个定时函数是:GetTickCount,timeGetTime,QueryPerformanceCounter(QPC)和RDTSC
我的建议是:
游戏逻辑时间应该用timeGetTime来完成。 这是简单,可靠,并有足够的解决方案的目的。 (编辑:默认分辨率不同 – 你可以调用timeBeginPeriod来强制它达到1毫秒的分辨率)
GetTickCount不应该被使用。 对于游戏逻辑或性能监控来说,分辨率太差(64赫兹 – 一个令人讨厌的频率,因为它会以典型的显示器刷新率创建拍频)。 这是最快的定时功能调用IIRC,但我找不到一个弥补其分辨率差的情况。 (编辑:有传言说,timeBeginPeriod可以提高GetTickCount的分辨率 – 这个传言是FALSE)
RDTSC和QPC对于简单的游戏逻辑时序来说太不可靠/古怪,但更适合于性能测量。 如果你想要独立于CPU频率变化的单元,RDTSC有一些问题会让你很痛苦,你通常需要使用asm来使用它。 QPC通常是可以工作的…但是当错误出现的时候,它可能会出错,而且出错的方式很多(有的时候真的很慢,有的时候频繁出现小的负三角形,有的时候也不经常出现大的负三角形(而不是环绕),有时候完全是精神病等)。 RDTSC几乎总是更快,通常分辨率更好。 总的来说,我更喜欢RDTSC的内部使用,只是因为它更快,从而在测量时间内产生更少的失真。 在客户机器上,这是一个非常接近的要求 – QPC由于微软的推动而更容易被证明是合理的,并且它常常没有任何复杂的情况,但是在客户机器上可能遇到的各种各样的方式,房子是我认为的主要缺点。
QPF / QPC是最好的,如果你需要一个高精度的计时器 (返回值是纳秒,但这并不意味着精度是1纳秒)。 否则,只需使用GetTickCount()
(以毫秒为单位)。 两个版本都应该正确处理可变的CPU频率(例如,在具有省电选项的笔记本电脑上)。
我不知道如何亲和面具可以帮助检索系统时间。
获得高精度时间的正确方法是调用QPF和QPC,并计算时间为:
double seconds = QPC / QPF;
编辑:
GetTickCount()的精度很差,比如5毫秒,但它仍然适用于大多数应用程序。 为了测量真正的小时间段,有一个选项:QPC / QPF。
我个人比较喜欢x86架构中的64位计数器的时间戳计数器,该计数器在每个内部时钟周期内递增。 它使用rdtsc指令读取,并返回edx:eax寄存器(x86-32)和rdx:rax(x86-64)中的计数器值。
教学方面有问题,但那是多年以前的事了。 今天的“绿色功能”导致负载相关的执行频率变化使得计算经过时间更加困难,但是经过的时钟周期不是问题。
unsigned long long startCycle, endCycle, elapsedCycles, overhead; // @ start of program overhead=instruction_rdtsc (); overhead=instruction_rdtsc ()-overhead; // preparing to measure startCycle=instruction_rdtsc (); // (sequence to measure) endCycle=instruction_rdtsc (); elapsedCycles=endCycle-startCycle-overhead;
指令本身的开销应该被确定。 我发现英特尔处理器的开销比AMD处理器要小。 开销应该多次测量 – 比如循环 – 找到最低的可能值。 测量的序列越长,开销就越小。 该指令可以在应用程序中插入永久的性能计量,以便能够在正常(非性能测试)执行下测量其实际性能。
由于流水线和无序执行问题,不应该测量很短的序列。 有人建议在rdtsc之前插入cpuid指令,但这只意味着实际的时钟数量大于它实际的数量。 我看到的周期数为30左右,而100左右或更高的周期总体上是可靠的。 中间有一个灰色地带。