Javascript requestAnimationFrame[now]与性能.now()时间差异
假设:rAFJavascript requestAnimationFrame[now]与性能.now()时间差异,javascript,timing,requestanimationframe,Javascript,Timing,Requestanimationframe,假设:rAF现在时间是在所有回调集合被触发时计算的。因此,在调用该帧的第一次回调之前发生的任何阻塞都不会影响rAFnow,而且它是准确的——至少对于第一次回调是如此 触发rAF集合之前进行的任何performance.now()测量值应早于rAFnow 测试:在之前记录(任何事情发生之前的基线时间)。设置下一个rAF。将rAFnow和实际的performance.now()与之前的进行比较,看看它们有多不同 预期成果: var before=performance.now(),frames=[
现在
时间是在所有回调集合被触发时计算的。因此,在调用该帧的第一次回调之前发生的任何阻塞都不会影响rAFnow
,而且它是准确的——至少对于第一次回调是如此
触发rAF集合之前进行的任何performance.now()测量值应早于rAFnow
测试:在之前记录(任何事情发生之前的基线时间)。设置下一个rAF。将rAFnow
和实际的performance.now()与之前的进行比较,看看它们有多不同
预期成果:
var before=performance.now(),frames=[“有阻塞”,“无阻塞”],calls=0;
requestAnimationFrame(功能帧(rAFnow){
var actual=performance.now();
log(“frame”+(calls+1)+“+frames[calls]+”:”;
log(“帧之前->rAF现在:”+(rAFnow-before));
log(“帧之前->rAF实际:”+(实际-之前));
如果(++调用 }
传递到requestAnimationFrame()
回调的时间戳是动画帧开始的时间。在同一帧中调用的多个回调都接收相同的时间戳。因此,如果performance.now()
在参数值之前返回一个时间,这将非常奇怪,但在参数值之后返回一个时间并不奇怪
当用户代理现在要为带有时间戳的文档运行动画帧回调时,它必须运行以下步骤:
如果文档对象的隐藏属性返回的值为true,则中止这些步骤。[网页可视性]
让回调是文档的动画帧回调列表中的条目列表,按照它们添加到列表中的顺序排列
将文档的动画帧回调列表设置为空列表
对于回调中的每个条目,顺序为:调用Web IDL回调函数,现在作为唯一参数传递,如果引发异常,则报告异常
因此,您已经为下一个动画帧注册了一个回调(假设只有一个)。嘀嗒嘀嗒,砰,动画帧发生的时间:
JavaScript运行库记录了现在的时间和标签
运行时将创建已注册动画帧回调列表的临时副本,并清除实际列表(这样,如果需要很长时间才能生成下一个动画帧,则不会意外调用这些列表)
列表中只有一件事:你的回调。系统以now作为参数调用该函数
您的回调开始运行。也许它以前从未运行过,所以JavaScript优化器可能需要做一些工作。或者,操作系统可能会将线程切换到其他一些系统进程,比如启动磁盘缓冲区刷新或处理一些网络流量,或者其他许多事情
哦,对了,你的回电。浏览器再次获取CPU,您的回调代码开始运行
您的代码调用performance.now()
,并将其与作为参数传入的now值进行比较
由于在步骤1和步骤6之间可能会经过一段短暂但不可忽略的时间,因此performance.now()
的返回值可能表示经过了几微秒,甚至超过了几微秒这是完全正常的行为。我在chrome上遇到了同样的问题,调用performance.now()
将返回一个比now
传递到window.requestAnimationFrame()
我的解决方法是使用传递到第一个窗口中回调的now
设置之前的。requestAnimationFrame()
而不是性能。now()
。似乎只使用这两个函数中的一个来测量时间可以保证时间值
我希望这能帮助其他受此bug困扰的人。我在您的代码片段中添加了一个暂停状态。可以随意回滚,但这样代码实际上会在某个时候完成:)。不,这很酷。谢谢,@MikeMcCaughan。你是说任何回调,即使是非rAF回调,都将具有相同的性能。now()值?事实似乎并非如此。如果你指的是多个皇家空军呼叫,我只使用一个皇家空军。我已经做了编辑,以便更好地解释发生了什么。(我不确定是否会收到通知?@whothehellistat no。当JavaScript运行时内部发生触发动画帧回调处理的事件时,时间戳会在该过程开始时记录一次。requestAnimationFrame()
注册的每个回调传递的时间值完全相同。它实际上与对performance.now()
的后续调用无关,只是它们显然都会在收集初始时间之后发生。这取决于系统上发生的情况(其他进程、操作系统工作等),完全有可能在动画帧内部收集帧开始时间戳和回调中的代码运行时间之间经过几微秒。特别是,系统不会将调用performance.now()
的结果传递给每个回调。因此,即使只有一个注册的回调,它的参数比performance.now()返回的值小也就不足为奇了。
@whothehellis答案稍微扩展了一点。