首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VB >

[原创分享]关于1ms精密度的计时延时器的基本测试

2013-12-02 
[原创分享]关于1ms精度的计时延时器的基本测试本帖最后由 bcrun 于 2013-11-30 11:44:27 编辑2013年11月30

[原创分享]关于1ms精度的计时延时器的基本测试
本帖最后由 bcrun 于 2013-11-30 11:44:27 编辑 2013年11月30日补充
之前写这篇文章时,因为已经使用win7一段较长的时间,所以没针对API帮助提到的Period方面的精度控制,在WinXP系统下做测试,后来找时间测试了下,不加timeBeginPeriod的话,那两个API在XP下精度远不到1ms。当初写这篇文章的主要目的,是闲聊一下自己测试代码执行速度的一些办法。现在打算结帖了,考虑到确实还有不少程序需要在winxp和win2003下使用,而且即使只在WIN7以上系统中运行,按官方的API说明,加上timeBeginPeriod的设置,也更严谨些,毕竟我也没看到哪里说,在WIN7下这个调用是可以省去的,搞不好在有些地方没调用timeBeginPeriod就不够精度呢。唉,不废话了,直接贴补充的代码。对了,有趣的是,加了timeBeginPeriod(1)后,在xp下多次测试那段DoTestSleep的代码,返回值都是2,不像win7下那样是1.

Public Declare Function timeBeginPeriod Lib "winmm.dll" (ByVal uPeriod As Long) As Long
Public Declare Function timeEndPeriod Lib "winmm.dll" (ByVal uPeriod As Long) As Long

Private Sub Form_Initialize()
    Call timeBeginPeriod(1)
End Sub

Private Sub Form_Terminate()
    Call timeEndPeriod(1)
End Sub


注意:这里说的1ms精度,只是指在适当条件(比如说CPU占用率不太高)下,用下述代码实测时,一般能达到的时间上的分辨率。就好像说一个人视力2.0,是指的他在准备充分条件下,去光线等条件符合相关标准的视力测试表前能测到2.0的水准,并不是说他在睡眼矇眬或长时间盯着电脑屏幕,或其它平时常见的生活状态下都能测试出有这个成绩。绝不能理解为“MS的windows系统能保证这些API实际执行时,所有情况都能有1ms的精度”。如果有“准确率”方面的严苛要求,建议多了解实时操作系统(RTOS)方面的知识。本人那方面了解不多,也就不多讨论了。

刚发了篇小博文,特别适合小白,考虑到论坛里很多人不怎么上博客,在这里也宣传一下
http://blog.csdn.net/bcrun/article/details/13772257
关于1ms精度的计时延时器的基本测试 

  一般来说,在平时编程中,出于优化代码运行速度等需求,常需要测算时间,这就需要对相关计时函数的精度做一番了解,不能老是糊里糊涂混日子。下面的测试由此而来

  首先,我们需要测出,常用的计时函数中哪个达到了1ms精度。先测GetTickCount

    '声明:  
    Declare Function GetTickCount Lib "kernel32" Alias "GetTickCount" () As Long  
    '说明  
    用于获取自windows启动以来经历的时间长度(毫秒)  
    '返回值  
    Long,以毫秒为单位的windows运行时间
  

如果只100000次的话,因为工作量太小,一般会输出0。不过不用担心,我们逐步加大循环次数,多测几次就行了。注意循环次数的跨度不要太大了,可以200000,300000这样的依次增加。这样你会发现,到了某一次,比如说500000,输出值会突然从0跳到16左右。可见这个API的实际精度只有约16ms.



    Private Sub DoTestGetTickCount()  
        Dim lTime1&, lTime2&  
        Dim i&  
        lTime1 = GetTickCount  
        For i = 1 To 400000  
          
        Next i  
        lTime2 = GetTickCount  
        Debug.Print lTime2 - lTime1  
    End Sub
  

写到这里时,可能已经有初学者急着要知道1ms精度的函数在哪了,别急,timeGetTime就是了:



    Private Declare Function timeGetTime Lib "winmm.dll" () As Long
  

测试代码几乎一样。测试结果为,在本人机器上,循环次数在100000时输出值就约为2-3了,次数增加1倍到200000的话,结果为4-5.如果减小到50000,则是1-2.可见,这个计时函数的精度为1ms.



    Private Sub DoTestTimeGetTime()  
        Dim lTime1&, lTime2&  
        Dim i&  
        lTime1 = timeGetTime  
        For i = 1 To 100000  
          
        Next i  
        lTime2 = timeGetTime  
        Debug.Print lTime2 - lTime1  
    End Sub
  

接下来,因为确认了timeGetTime的精度可以达到1ms,我们可以放心测算延时函数sleep的实际精度了,先公布结果,1ms.


    Private Sub DoTestSleep()  
        Dim lTime1&, lTime2&  
        Dim i&  
        lTime1 = timeGetTime  
      
        Sleep 1 'delay 1 ms  
        lTime2 = timeGetTime  
        Debug.Print lTime2 - lTime1  
    End Sub
  


最后补充说明一下,获取UTC时间的GetSystemTime和相应的SystemTimeToFileTime,实际精度也是1ms timeGetTime sleep


[解决办法]
Windows NT:该函数的时间精度是五毫秒或更大一些,这取决于机器的性能。可用timeBeginPeriod和timeEndPeriod函数提高timeGetTime函数的精度。如果使用了,连续调用timeGetTime函数,一系列返回值的差异由timeBeginPeriod和timeEndPeriod决定。
[解决办法]
timeGetTime与操作系统和机器性能本身有关的,高精度计时器一般都是用QueryPerformanceCounter 配合QueryPerformanceFrequency函数的。
[解决办法]
有个很有名的软件叫变速齿轮,也许现在知道的人不多了,可是我们学生时代的回忆啊。

它就是通过hook GetTickCount欺骗软件实现变速的。
[解决办法]
与操作系统和硬件有关吧
[解决办法]



我在csdn上传了两个测量时间的 C++ 类,精确到 毫秒
[解决办法]
嗯,写的不错,QueryPerformanceFrequency可以获得更高
[解决办法]
变速齿轮--满满的回忆
[解决办法]
sleep 不是用来计时的,是把线程时间片释放掉一些,所以他不存在精度的问题;每次调用sleep貌似都是释放当前的时间片。。。
[解决办法]
KeDelayExecutionThread可以达到百纳秒精度,NdisMSleep可以达到1微秒精度
[解决办法]

[解决办法]

你这样说,未免有点儿过分了。
这些东西如果M$不公布具体细节方面的资料,谁又能够知道它的真实运行机会?
都只不过是一些推论、猜测罢了!

如果照你的说法,那sleep带个时间参数干什么?那不是多此一举?

既然它带了一个“以毫秒为单位的时间参数”,并且是实实在在的起到了作用的。
那我们对这个“时间”的精度问题进行一些探讨,又有何不可呢?
[解决办法]
非常不错,很好很实用
[解决办法]

[解决办法]
不错,挺有用的
------解决方案--------------------



[解决办法]


既然讨论技术,那咱不扯面子了。针对下面代码,俺给出测试结论:xp和win7结果不同,不同的硬件配置返回值也不同。修改首帖吧,赶紧的。[原创分享]关于1ms精密度的计时延时器的基本测试


既然讨论技术,那咱不扯面子了。针对下面代码,俺给出测试结论:xp和win7结果不同,不同的硬件配置返回值也不同。修改首帖吧,赶紧的。[原创分享]关于1ms精密度的计时延时器的基本测试

    Private Sub DoTestSleep()  
        Dim lTime1&, lTime2&  
        Dim i&  
        lTime1 = timeGetTime  
       
        Sleep 1 'delay 1 ms  
        lTime2 = timeGetTime  
        Debug.Print lTime2 - lTime1  
    End Sub


看了好几个帖子,也不知道你们到底在争论什么

这个什么也证明不了,sleep不是用来计时的,用sleep测试时钟精确性非常不恰当

这种测试结果,大概只能表示为系统的繁忙程度

用sleep会导致线程切换,估计那样代码每次的测试结果都不相同,而不相同的原因也有很多种,其中之一是timegettime的精度,另外就是系统内的线程环境,还有就是系统对线程调度的算法问题

总之。。。 这个题目,lz的到底怎么想的用 sleep 测试精度。。。。

[解决办法]
斑竹辛苦了.........
[解决办法]
我一般用高精度频率计数器的2个API。

热点排行