函数原型:time_t time(time_t * timer)
功能:返回以格林尼治时间(GMT)为标准,从1970年1月1日00:00:00到现在的此时此刻所经过的秒数。
如: localtime, gmtime, asctime, ctime也可以获得当前系统时间或是标准时间.
注意: 用difftime函数可以计算两个time_t类型的时间的差值, 例如: difftime(t2, t1), 我们也可以t2 - t1, 但是time()返回的值单位不一定是秒, 所以使用difftime()更可靠。
time_t start, end, ttt; time(&start); Sleep(1000); time(&end); ttt = difftime(end, start);
DWORD GetTickCount(void);
定义:
For Release configurations, this function returns the number of milliseconds since the device booted, excluding any time that the system was suspended. GetTickCount starts at 0 on boot and then counts up from there.
在Release版本中,该函数从0开始计时,返回自设备启动后的毫秒数(不含系统暂停时间)。
For Debug configurations, 180 seconds is subtracted from the the number of milliseconds since the device booted. This allows code that uses GetTickCount to be easily tested for correct overflow handling.
在Debug版本中,设备启动后便从计时器中减去180秒。这样方便测试使用该函数的代码的正确溢出处理。
Return Values
The number of milliseconds indicates success.
返回值:如正确,返回毫秒数。
unsigned long lBegin, lEnd; lBegin = ::GetTickCount(); Sleep(1000); lEnd = ::GetTickCount(); unsigned long l = lEnd - lBegin;
clock_t clock(void); 这个函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时间(wal-clock).
unsigned long tBegin = ::clock(); Sleep(1000); unsigned long tEnd = ::clock(); unsigned long ll = (tEnd - tBegin) * 1000 / CLK_TCK; // 通常CLK_TCK就是1000, 为了效率, tEnd - tBegin就是毫秒数了 // 但是也要看CLK_TCK
函数原型:DWORD timeGetTime(VOID);
功能:返回系统时间,以毫秒为单位。系统时间是从系统启动到调用函数时所经过的毫秒数.
注意: 这个值是32位的,会在0到2^32之间循环,约49.71天; 并且精度不是很高; 可用timeBeginPeriod和timeEndPeriod函数提高timeGetTime函数的精度.
没有精度, 使用又麻烦, 而且有其他方法获得毫秒级的计时, 所以这种方法基本上不使用.
#include "Mmsystem.h" #pragma comment(lib,"Winmm.lib") DWORD dwStart, dwEnd; dwStart = timeGetTime(); Sleep(1000); dwEnd = timeGetTime(); DWORD dw = dwEnd - dwStart;
从GetTickCount和clock的说明中可以知道:
1. 可以使用GetTickCount计算电脑开机持续时间.
2. 可以使用clock计算某个进程的运行持续时间.
3. timeGetTime需要手动添加lib, 而且精度可能会不好, 所以甚至可以不使用.
原型:BOOL QueryPerformanceFrequency(LARGE_INTERGER *lpFrequency);
功能:返回硬件支持的高精度计数器的频率(每秒钟的CPU Tick数)
原型:BOOL QueryPerformanceCounter(LARGE_INTEGER *lpCount);
功能:返回高精度计数器的计数值
所以: 消逝时间 = (EndTick - BeginTick) / TickPreSecond; (单位是秒, 精度可以达到微秒(看你的硬件而定))
LARGE_INTEGER llTemp, llBegin1, llEnd1; ::QueryPerformanceFrequency(&llTemp); // 获取CPU时钟频率 3220820 kHZ ::QueryPerformanceCounter(&llBegin1); // 获取开始计数值 54826082774 Sleep(100); ::QueryPerformanceCounter(&llEnd1); // 获取结束计数值 54826404859 double d = (llEnd1.QuadPart - llBegin1.QuadPart) / (llTemp.QuadPart * 1000.0); // 单位是秒, 精确到微秒
说明:
1. 调用QueryPerformanceFrequency时, 我的电脑返回的值是3220820, 很明显, 其单位是kHZ(我的CPU主频是3.2GHZ)
2. 也就是说3220820倒数一下, 精度也只能达到微秒级了.
这是X86架构CPU汇编指令
指令: RDTSC (操作码: 0x0F 0x31)
功能: 将时间标签计数器读入EDX:EAX寄存器中.
说明: 在Pentium以上的CPU中,提供了一条机器指令RDTSC来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数返回值的寄存器, 所以我们可以把这条指令看成是一个普通的函数调用.
inline unsigned __int64 GetRDTSC() { __asm RDTSC } // 如果编译器不允许直接用RDTSC的话,可以用_emit伪指令直接嵌入该指令的机器码形式0x0F 0x31: inline unsigned __int64 GetRDTSC() { __asm _emit 0x0F __asm _emit 0x31 }
GetRDTSC得到CPU跳了多少次, 如果我们知道跳一次的用时, 就可以算出持续时间.
跳一次的用时 = 1 / CPU主频 (单位: 秒)
Windows平台下可以使用QueryPerformanceFrequency()函数获得CPU的主频, 但是在标准C/C++中没有这样的函数.
你可以间接发计算出主频, 例如:
unsigned __int64 GetCPUHZ() { unsigned __int64 nBegin = GetRDTSC(); Sleep(1000); unsigned __int64 nEnd = GetRDTSC(); return (nEnd - nBegin); }
说明:
1. 这个函数的误差在于Sleep(1000)的执行时间不是1秒, 可能是1.0002秒.
2. QueryPerformanceFrequency得到的主频的单位是 kHZ, 也就是说其精度只能达到微秒, 而不是纳秒.
unsigned __int64 nHZ = GetCPUHZ(); unsigned __int64 nBegin = GetRDTSC(); ... unsigned __int64 nEnd = GetRDTSC(); double dTime = (nEnd - nBegin) * 1.0 / nHZ;// 单位是秒, 精度甚至可以达到纳秒
说明:
1. 这里的精度可以达到纳秒, 但是在纳秒级可能不是很准, 因为GetCPUHZ() 得到主频有误差.
2. 纳秒计时的粒度最小, 所以你也可以使用这种方法进行微秒, 毫秒, 秒的计时.
1. 计时与定时不同, 这里计时可以达到纳秒级, 但是定时就不能(因为执行一条指令可能至少要100纳秒).