我 们在衡量一个函数运行时间,或者判断一个算法的时间效率,或者在程序中我们需要一个定时器,定时执行一个特定的操作,比如在多媒体中,比如在游戏中等,都 会用到时间函数。还比如我们通过记录函数或者算法开始和截至的时间,然后利用两者之差得出函数或者算法的运行时间。编译器和操作系统为我们提供了很多时间 函数,这些时间函数的精度也是各不相同的,所以,如果我们想得到准确的结果,必须使用合适的时间函数。现在我就介绍 windows 下的几种常用时间函数。
1 : Sleep 函数
使用: sleep(1000) ,在 Windows 和 Linux 下 1000 代表的含义并不相同, Windows 下的表示 1000 毫秒,也就是 1 秒钟; Linux 下表示 1000 秒, Linux 下使用毫秒级别的函数可以使用 usleep 。
原理: sleep 函数是使调用 sleep 函数的线程休眠,线程主动放弃时间片。当经过指定的时间间隔后,再启动线程,继续执行代码。 Sleep 函数并不能起到定时的作用,主要作用是延时。在一些多线程中可能会看到 sleep(0); 其主要目的是让出时间片。
精度: sleep 函数的精度非常低,当系统越忙它精度也就越低,有时候我们休眠 1 秒,可能 3 秒后才能继续执行。它的精度取决于线程自身优先级、其他线程的优先级,以及线程的数量等因素。
2 : MFC 下的 timer 事件
使用: 1. 调用函数 SetTimer() 设置定时间隔,如 SetTimer(0,100,NULL) 即为设置 100 毫秒的时间间隔; 2. 在应用程序中增加定时响应函数 OnTimer() ,并在该函数中添加响应的处理语句,用来完成时间到时的操作 。
原理: 同sleep 函数一样。不同的是timer 是一个定时器,可以指定回调函数,默认为OnTimer() 函数。
精度: timer 事件的精度范围在毫米级别,系统越忙其精度也就越差。
3 : C 语言下的 Time
使用: time_t t;time(&t);Time 函数是获取当前时间。
原理: time 函数主要用于获取当前时间,比如我们做一个电子时钟程序,就可以使用此函数,获取系统当前的时间。
精度: 秒级别
4 :COM 对象中的 COleDateTime , COleDateTimeSpan 类
使用: COleDateTime start_time = COleDateTime::GetCurrentTime();
COleDateTimeSpan end_time = COleDateTime::GetCurrentTime()-start_time;
While(end_time.GetTotalSeconds() < 2)
{
//
处理
延时或定时期间能处理其他的消息
DoSomething()
end_time = COleDateTime::GetCurrentTime-start_time;
}
原理: 以上代表延时2 秒,而这两秒内我们可以循环调用DoSomething() ,从而实现在 延时的时候我们也能够处理其他的函数,或者消息。 COleDateTime,COleDateTimeSpan 是 MFC 中 CTime , CTimeSpan 在 COM 中的应用,所以,上面的方法对于 CTime , CTimeSpa 同样有效。
精度: 秒级别
5 : C 语言下的时钟周期 clock()
使用:
clock_t start = clock();
Sleep(100);
clock_t end = clock();
double
d = (double
)(start - end) / CLOCKS_PER_SEC;
原理: clock() 是获取计算机启动后的时间间隔。
精度: ms 级别,对于短时间内的定时或者延时可以达到 ms 级别,对于时间比较长的定时或者延迟精度还是不够。在 windows 下 CLOCKS_PER_SEC 为1000 。
6 : Windows 下的 GetTickCount()
使用:
DWORD start = GetTickCount();
Sleep(100);
DWORD end = GetTickCount();
原理: GetTickCount() 是获取系统启动后的时间间隔。通过进入函数开始定时,到退出函数结束定时,从而可以判断出函数的执行时间,这种时间也并非是函数或者算法的真实执行时间,因为在函数和算法线程不可能一直占用CPU , 对于所有判断执行时间的函数都是一样, 不过基本上已经很准确, 可以通过查询进行定时。 GetTickCount() 和 Clock() 函数是向主板 BIOS 要 real time clock 时间,会有中断产生,以及延迟问题。
精度: WindowsNT 3.5 以及以后版本精度是10ms ,它的时间精度比clock 函数的要高,GetTickCount() 常用于多媒体中。
7 : Windows 下 timeGetTime
使用: 需要包含 Mmsystem.h , Windows.h ,加入静态库 Winmm.lib.
timeBeginPeriod(1);
DWORD start = timeGetTime();
Sleep(100);
DWORD end = timeGetTime();
timeEndPeriod(1);
原理: timeGetTime 也时常用于多媒体定时器中,可以通过查询进行定时。通过查询进行定时,本身也会影响定时器的定时精度。
精度: 毫秒 ,与 GetTickCount() 相当。但是和 GetTickCount 相比, timeGetTime 可以通过 timeBeginPeriod ,timeEndPeriod 设置定时器的最小解析精度, timeBeginPeriod,timeEndPeriod 必须成对出现。
8 :windows 下的 timeSetEvent
使用:还记的 VC 下的 Timer 吗? Timer 是一个定时器,而以上我们提到几种时间函数或者类型,实现定时功能只能通过轮训来实现,也就是必须另外创建一个线程单独处理,这样会影响定时精度,好在 windows 提供了内置的定时器 timeSetEvent ,函数原型为
MMRESULT timeSetEvent
(
UINT uDelay, //
以毫秒指定事件的周期
UINT uResolution, //
以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为
1ms
LPTIMECALLBACK lpTimeProc, //
指向一个回调函数
WORD dwUser, //
存放用户提供的回调数据
UINT fuEvent
)
//
标志参数,
TIME_ONESHOT
:执行一次;
TIME_PERIODIC
:周期性执行
具体应用时,可以通过调用 timeSetEvent() 函数,将需要周期性执行的任务定义在 lpFunction 回调函数中 ( 如:定时采样、控制等 ) ,从而完成所需处理的事件。需要注意的是:任务处理的时间不能大于周期间隔时间。另外,在定时器使用完毕后,应及时调用 timeKillEvent() 将之释放。
原理: 可以理解为代回调函数的 timeGetTime
精度:
毫秒
,
timeSetEvent
可以通过
timeBeginPeriod
,timeEndPeriod
设置定时器的最小解析精度, timeBeginPeriod,timeEndPeriod
必须成对出现。
9
:高精度时控函数
QueryPerformanceFrequency
,
QueryPerformanceCounter
使用:
LARGE_INTEGER m_nFreq;
LARGE_INTEGER m_nBeginTime;
LARGE_INTEGER nEndTime;
QueryPerformanceFrequency(&m_nFreq); //
获取时钟周期
QueryPerformanceCounter(&m_nBeginTime); //
获取时钟计数
Sleep(100);
QueryPerformanceCounter(&nEndTime);
cout << (nEndTime.QuadPart-m_nBeginTime.QuadPart)*1000/m_nFreq.QuadPart << endl;
原理: CPU 上也有一个计数器,以机器的clock 为单位,可以通过rdtsc 读取,而不用中断,因此其精度与系统时间相当。
精度: 计算机获取硬件支持,精度比较高,可以通过它判断其他时间函数的精度范围。
10
小结:
以上提到常用的
9
种时间函数,由于他们的用处不同,所以他们的精度也不尽相同,所以如果简单的延时可以用
sleep
函数,稍微准确的延时可以使用
clock
函数,
GetTickCount
函数,更高级的实用
timeGetTime
函数;简单的定时事件可以用
Timer
,准确地可以用
timeSetEvent
;或取一般系统时间可以通
time
,或者
CTime
,或者
COleDateTime
,获取准确的时间可以用
clock
,或者
GetTickCount
函数,或者
timeGetTime
函数,而获取准确地系统时间要使用硬件支持的
QueryPerformanceFrequency
函数,
QueryPerformanceCounter
函数。
本文介绍了Windows环境下九种常用时间函数的使用方法、原理及精度,包括Sleep、Timer、Time、COleDateTime、Clock、GetTickCount、timeGetTime、timeSetEvent及QueryPerformanceCounter等。
2189

被折叠的 条评论
为什么被折叠?



