• 再谈JavaScript时钟中的16ms精度问题.


    上一篇BLOG中,通过测试我们发现 JavaScript的时钟是16ms的间隔. 对于IE来说,每次总会发生16ms的间隔;对于firefox来说,会存在0ms的间隔. 对于后者,我曾解释说:可能是Java使用了自己的时钟.

    先说第二种情况,对于firefox中的js引擎,我尚未去看代码,因此我只说"可能",但后来hax来说,firefox的JS引擎仍是C写的,这才想起的确如此.所以这里先说,我前面关于firefox的问题的解释是错的.

    再说16ms的问题. 我其实也怀疑,为什么是16ms,而不是其它的什么值呢?

    hax给了我很多信息.我这里来整理一下:

    首先是取时间值.也就是我们在JavaScript中用new Date()得到时间值采用的方法其实是不准确的. 该值总会是15~16ms的间隔值,其原因在于:
    ---------------
    Windows系统获取时间主要是用下面的几种方法
      一:GetTickCount()
          这个就是用的上篇里说的系统时钟中断
      Windows NT 3.5 及更高版本,精度为 10ms(100Hz)
      Windows NT 3.1 ,精度为 16ms(60Hz)
      Windows 95 及更高版本,精度为 55ms(18.2Hz)
      (对于Windows XP(NT5.0) 及更高版本,实测得的精度为 16ms)
      
      二:timeGetTime()
      精度约1ms(需通过其它API配合)

      三:High-Resolution Timer
          这种方法就使用了CPU的RTC
      QueryPerformanceCounter() 配合 QueryPerformanceFrequency(),适用于高精度应用场合

    参见:http://www2.matrix.org.cn/thread.shtml?topicId=10491&forumId=1&fid=1
    ---------------
    也就是说,如果JavaScript的new Date()采用getTickCount()来实现,那么它必然是返回16ms间隔的时间值的.
    举例来说,你可能写一个超大循环用来收集一批Date()对象,最终你会发现,大多数时候是一样的值,而每两
    批时间值的差值总在15~16ms.

    接下说时间精度.也就是讨论setTimeout/setInterval()为什么是16ms,而另外一些人/资料会提及到10ms这个精度值.首先我们来看时钟的实现:
    ---------------
      一、使用系统时钟SetTimer()
      系统时钟是采用向窗体发WM_TIMER事件来激活处理例程的。而且同一个窗体消息队列中只允许同时存在一个WM_TIMER,因此它可能被丢失消息。

      二、使用timeSetEvent()
      可以使用timeSetEvent()来设置时钟。缺省情况下,他是16ms精度的。另外,同进程中同时最多有16个timeSetEvent()。

      三、在线程中使用sleep()
      Zhe曾用C代码做过测试,证明sleep()的精度是10ms。也就是说,sleep(1)产生的效果最低限也是10ms的间隔。

    参见:http://dev.cbw.com/vc/progress/200510315005_4279849.shtml
    ---------------

    timeSetEvent缺省情况下是16ms/10ms间隔的,更确切地说,是“对于Intel 芯片的精度为16ms,对于MIPS芯片的精度为10ms”。这一点在下面这份文档中有说明:
    http://www.wanfangdata.com.cn/qikan/periodical.Articles/jdgc/jdgc99/jdgc9903/990318.htm

    timeSetEvent()可以通过一些API:timeBeginPeriod()来调整计时精度。这一点请参考:
    http://www.vckbase.com/document/viewdoc/?id=1234

    最后,我们来讲结论。对于JavaScript来说,由于new Date()只需要得到毫秒值,并不需要过高的精度,因此最合理的方法当然是调用GetTickCount()来取值,而不是采QueryPerformanceCounter() 配合 QueryPerformanceFrequency()来得到高精度的时间值。由于GetTickCount()自身的限制,JavaScript的new Date()得到的时间隔是16ms精度的。——对于win98或其它系统来说,这个值可能是58ms/10ms。

    对于定时器来说,JavaScript应该会是使用timeSetEvent()来做定时器。因为如果用线程+sleep()会存在较大的开销(事实上我出观察到线程计数是没有变化的),而采用SetTimer()会存在消息队列的问题。所以采用timeSetEvent()是最实际的方案。——至于16个timeSetEvent()的限制,可以通过同一个timeSetEvent()中处理多个例程来规避。因此,由于timeSetEvent()自身在缺省状态下的限制,因此导致了16m时间间隔。

    对于FireFox中的和WebKit(safari)中的脚本引擎,因为是开源的,有兴趣的不妨自己读读相关的代码。就不再讲述了。

    感谢Zhe和hax对我提供的帮助。本文基本上是资源整理贴。^.^

  • 相关阅读:
    silverlight 之 – Blend 之 Style for Button (三)
    silverlight 之 – Blend 一切源于Brush(一)
    silverlight 之 – Blend 之 Accordion (五)
    ASp.net下 fckeditor 配置图片上传最简单的方法
    ubuntu 升级java7
    ubuntu下远程登录mysql
    Tomcat 连接池 数据源配置
    wget使用方法命令详解
    修改mysql提示符
    chrome 的几种about
  • 原文地址:https://www.cnblogs.com/encounter/p/2188689.html
Copyright © 2020-2023  润新知