用于更精确测量时间间隔的 C++ 类






4.66/5 (25投票s)
能够在 Windows 操作系统下以微秒为单位测量时间间隔的 C++ 类。
引言
这个计时器类能够以微秒为单位测量 Windows 操作系统下的时间间隔。它使用不太为人所知的 Windows API 函数 QueryPerformanceFrequency()
和 QueryPerformanceCounter()
来获取高精度性能计数器的频率和计数。对于没有这种高精度性能计数器的系统,将使用更常用的 API 函数 GetTickCounts()
,但这会降低计时器的精度。无论如何,计时器的可靠性取决于系统的硬件性能,也就是说,对于处理器频率更高的系统,精度会提高。该类还演示了一些关于在 VC++ 中使用 __int64
整数的有用技巧。
实现
在这里,我只展示了 CPreciseTimer
类的公共用户界面,实现细节在演示项目的源代码文件中。
class CPreciseTimer { public: CPreciseTimer(); bool SupportsHighResCounter(); void StartTimer(); void StopTimer(); __int64 GetTime(); };
构造函数
CPreciseTimer()
在首次实例化该类时,还会确定是否可以使用高精度性能计数器,如果可以使用,则初始化频率成员变量。后续构造不会重复这个计算块。函数
SupportsHighResCounter()
仅当高精度性能计数器可用时才返回 true。它为用户提供了关于计时器精度的提示。函数
StartTimer()
,顾名思义,是启动计时器。函数
StopTimer()
停止计时器,同时保留自计时器启动以来经过的时间。函数
GetTime()
如果计时器处于运行状态,则返回自计时器启动以来经过的时间间隔。如果计时器处于停止状态,则返回上次停止调用和上次启动调用之间的时间差。返回值以微秒为单位,但如果高精度性能计数器不可用,则不能信任该值,在这种情况下,精度实际上不可能高于毫秒级。
如何使用
以下代码片段显示了一个简单的使用示例
CPreciseTimer oPreciseTimer; cout << "Starting!" << endl; oPreciseTimer.StartTimer(); ::Sleep(5000); cout << "Ending!" << endl; oPreciseTimer.StopTimer(); __int64 i64Diff = oPreciseTimer.GetTime(); cout << "Diff=" << Int64ToString(i64Diff) << endl; return 0;
我使用自己的函数 Int64ToString()
来显示 __int64
数字。我也免费提供此函数供您使用
string Int64ToString(__int64 const& ri64, int iRadix=10) { bool bNeg = (ri64 < 0); __int64 i64 = ri64; string ostrRes; bool bSpecial = false; if(true == bNeg) { i64 = -i64; if(i64 < 0) // Special case number -9223372036854775808 or // 0x8000000000000000 bSpecial = true; ostrRes.append(1, '-'); } int iR; do { iR = i64 % iRadix; if(true == bSpecial) iR = -iR; if(iR < 10) ostrRes.append(1, '0' + iR); else ostrRes.append(1, 'A' + iR - 10); i64 /= iRadix; } while(i64 != 0); //Reverse the string string::iterator it = ostrRes.begin(); if(bNeg) it++; reverse(it, ostrRes.end()); return ostrRes; }
它能够以任何基数(默认基数为 10)显示 __int64
值。__int64
值也可以使用 printf()
函数显示,如下代码片段所示
__int64 i64 = 0x7fffffffffffffff; printf("Decimal Value = %I64d\n", i64); printf("Hexa Value = %I64x\n", i64);
您也可以在 MFC 应用程序中使用 CString
的 Format()
函数
CString str; str.Format("%I64d", 4294967307);
或者一个 stdlib 函数 _i64toa()
,它类似于 itoa()
__int64 i64 = 4294967307; char szBuff[20]; _i64toa(i64, szBuff, 10);
结论
本文附带的项目包含了所介绍的 CPreciseTimer
类和测试代码的源代码。我对有关此实现的任何意见和新想法都感兴趣。