huyutian

他强由他强,清风拂山岗;他横由他横,明月照大江。他自狠来他自恶,我自一口真气足

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  20 随笔 :: 47 文章 :: 22 评论 :: 0 Trackbacks
最近有个项目需要准确计量时间,在网上搜索了一些相关资料,汇总摘抄在此。
Windows是一个抢占式多任务系统,要准确测量时间(达到毫秒级精度)是比较困难的,下面简易对比分析一下Windows所提供的毫秒级时间相关函数。
方法1:
void WINAPI GetSystemTime(LPSYSTEMTIME lpSystemTime);
typedef struct _systemtime {   
word wyear;   
word wmonth;   
word wdayofweek;   
word wday;   
word whour;   
word wminute;   
word wsecond;   
word wmilliseconds;   
} systemtime, *psystemtime;  
取得当前系统日期和时间,最小精度为毫秒。具体参见https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms724390%28v=vs.85%29.aspx
方法2:
void WINAPI GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime );
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime; } FILETIME, *PFILETIME;
结构包含一个64位的数值,代表UTC时间1601年1月1日开始到现在的计数器,计数间隔为100纳秒。可以通过调用FileTimeToSystemTime函数转换为标准时分秒形式。
具体参见https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms724397%28v=vs.85%29.aspx
方法3:
DWORD WINAPI GetTickCount(void);
获取从系统启动到现在的毫秒数。参见https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms724408%28v=vs.85%29.aspx
方法4:
DWORD timeGetTime(void);
也是获取从系统启动到当前的毫秒数值,是微软在游戏、多媒体库提供的一个函数。调用时需要包含Winmm.lib库
具体参见https://msdn.microsoft.com/zh-cn/library/windows/desktop/dd757629%28v=vs.85%29.aspx
方法5:
BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);
这个是微软Windows所提供最高级别的时间计数器,据称时戳的最高精度小于1us。参见https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms644904%28v=vs.85%29.aspx
照说有这么多时间精度可供选择,问题应该很好解决,但事情并不是这么简单。QueryPerformanceCounter这个最为微软推荐的高精度时间函数是有缺陷的,当处理器有多个内核时,
QueryPerformanceCounter计数器会做相应的调整以保持准确。但由于某些BIOS的bug,线程切换时QueryPerformanceCounter计数器可能会返回不同的数值。因此微软建议尽量在一个核上执行
QueryPerformanceCounter计时。相关说明参见Game Timing and Multicore Processors一文(https://msdn.microsoft.com/en-us/library/ee417693(v=vs.85).aspx

关于
QueryPerformanceCounter使用注意事项
1.
QueryPerformanceFrequency只需要调用一次就够了,这个频率值在系统运行期间不会改变。
2.尽量在单进程和单线程、单内核环境下调用
QueryPerformanceCounter使用 Windows API SetThreadAffinityMask可以设置某个线程只在单处理器执行。
3.在多个线程中使用
QueryPerformanceCounter可能显著的降低多内核系统的性能。
4.在系统休眠或者超频情况下使用
QueryPerformanceCounter计时可能会不准确。

综合比较Windows时间函数,计时精度
QueryPerformanceCounter > timeGetTime > GetTickCount ,GetTickCount的精度大约是55ms左右(1个Tick),
timeGetTime实际上也是用QueryPerformanceCounter除以频率换算出来的,所以应该比GetTickCount要准确些。
读取准确UTC时间GetSystemTimeAsFileTime > GetSystemTime。更准确的系统时间读取可以结合GetSystemTimeAsFileTime与QueryPerformanceCounter来计算。详细可参见定时器:为 Windows 实现一个连续更新,高精度的时间供应器一文。
英文原文在这里:https://msdn.microsoft.com/en-us/magazine/cc163996.aspx,对应的中文翻译看这里:http://www.vckbase.com/index.php/wv/776
关于GetSystemTimeAsFileTime与GetSystemTime的比较分析可参见http://www.cnblogs.com/walfud/articles/3242825.html一文。




posted on 2015-04-10 13:02 胡雨田 阅读(2235) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理