Google chrome devtools 了解Chrome开发工具时间表

Google chrome devtools 了解Chrome开发工具时间表,google-chrome-devtools,jank,Google Chrome Devtools,Jank,我试图理解为什么Chrome开发工具会报告几个长框架 flame图表中的第一行(调用堆栈的顶部)主要是计时器触发的事件,由执行一系列$(function(){})的jQuery.Deferred()触发就绪函数 如果我深入研究jQuery源代码,并用requestAnimationFrame替换它们对setTimeout的使用,火焰图不会有太大变化,我仍然会得到许多RAF在单个帧内发射(如开发工具所报告的),从而产生长帧。我本来希望执行以下伪代码: window.requestAnimatio

我试图理解为什么Chrome开发工具会报告几个长框架

flame图表中的第一行(调用堆栈的顶部)主要是
计时器触发的
事件,由执行一系列
$(function(){})的
jQuery.Deferred()触发就绪函数

如果我深入研究jQuery源代码,并用
requestAnimationFrame
替换它们对
setTimeout
的使用,火焰图不会有太大变化,我仍然会得到许多RAF在单个帧内发射(如开发工具所报告的),从而产生长帧。我本来希望执行以下伪代码:

window.requestAnimationFrame(function() {
    // do stuff
});

window.requestAnimationFrame(function() {
    // do more stuff
});
在两个不同的动画帧上执行。不是这样吗

所有正在执行的JS都是必要的,但是当
setTimeout
rAF
似乎无法实现这一点时,我应该如何将其作为“微任务”执行(如所暗示的,但此处未解释)

更新

这是一个放大的镜头,其中一个长帧似乎没有任何回流(强制或其他)。为什么这里所有的rAF回调都在一个帧内执行


长帧通常是由强制同步布局引起的,这是您(无意中)强制布局操作提前发生的情况

当您写入DOM时,布局需要回流,因为它已被写入操作失效。这通常发生在下一帧。但是,如果您尝试从DOM中读取,则布局会在当前帧中提前进行,以确保返回正确的值。当强制布局发生时,会导致长帧,从而导致jank

为了防止这种情况发生,您应该只在
requestAnimationFrame
函数中执行写入操作。读取操作应在此之外进行,以避免浏览器过早布局

这是一篇解释得很好的文章,有一个简单的示例演示,用于检测DevTools中的强制回流,以及如何解决它

它可能也值得一看,这是一个用于批处理读写操作的库。它基本上是一个排队系统,并且更具可扩展性

其他来源: 由Paul Irish编写,包含将强制布局/回流的属性和方法的全面列表

更新:至于假设多个
requestAnimationFrame
调用将在单独的帧上执行回调,情况并非如此。连续调用时,浏览器会将回调添加到动画回调的文档列表中。当浏览器运行下一帧时,它将遍历文档列表并按照添加的顺序执行每个回调

有关更多实现细节,请参见HTML规范


这意味着您应该避免使用连续调用,特别是在回调函数执行时间总和超过帧预算的情况下。我认为这可以解释不是回流造成的长帧

显然,第一个rAF超出了帧预算,因此浏览器切换到长帧并执行第二个rAF。使用一个rAF可能:对于微任务,您可能可以通过在某个不可见节点上使用属性为true的MutationObserver,然后更改属性来触发一个rAF。@wOxxOm谢谢,这在理论上是有意义的,但我看不出这是怎么回事,特别是在第二个屏幕截图中,我添加了^Hi@Gideon,谢谢,我更新了屏幕截图以显示更高的高度。最右边的3个强制回流是故意的(由于页面设计)。其他没有强制回流的帧呢?它们也很“长”,但Chrome没有抱怨强制回流?你知道为什么多个rAF回调被批处理成单个帧,使其变长吗?我看了一下规范,结果发现每次调用
requestAnimationFrame
函数时,浏览器都会将动画回调附加到文档级别的回调列表中,然后在浏览器运行它们时遍历并调用它们。因此,您正在有效地将回调合并到一个帧中,使其变长。是的,只需将我所有的
jquery.ready
settimeout
替换为
fastdom.defer
,现在它们都在各自的帧中执行。温拉尔