我正在尝试测量 Chrome 中交互的用户感知延迟。这是从按键到屏幕更新的时间。在此示例中,我们将使用新内容重新渲染大部分屏幕。不涉及网络延迟,我们只是更新 HTML。
在下面的屏幕截图中,您可以看到 Chrome DevTools keydown 事件,它运行了很多 javascript,然后是一堆绘画、合成等,然后 keydown 事件“Response”跨度结束。
假设水平灰线是 vsync(有人知道这些线是否在任何地方记录了吗?)在 Chrome 向 GPU 和屏幕写入新渲染的地方,它似乎是 Devtools 为 keydown 提供的“响应”跨度事件是我要测量的一个很好的近似值,因为它测量的是从按下键到我们完成 DOM 变异后第一条灰线之后的时间。
我已经尝试了多种方法在 javascript 中估算这段时间,包括使用 requestAnimationFrame、requestIdleCallback、带有消息传递的 setImmediate polyfill,以及上述的一些组合。看起来它们都比纯 Javascript 时间长,但大多数情况下它们低估或高估了实际更新屏幕的时间。
有谁知道在生产中衡量这段时间的更好方法吗? Chrome DevTools 指标如何运作?我应该完全测量其他东西吗?
最佳答案
这些输入延迟事件的检测非常复杂和酷。这些都是很好的问题。
输入延迟事件结束时间
输入延迟事件在 VSYNC 附近结束,假设它们触发的工作导致需要屏幕更新的失效。这就是为什么在您的屏幕截图中,Key Down 比 Key Up 延伸得更远。 (即使有 keyup
监听器,它们也不会使样式/布局无效)
当然有可能存在这些事件终止的早期绘制和 VSYNC,当屏幕随着对输入的响应而更新时并不是真的……但您必须自己进行调用。
灰色虚线、vsync、交换缓冲区
灰色虚线是框架边界,但这里开始变得棘手。在 Chrome(和 AFAIK,其他浏览器也一样)中有主线程框架和合成器线程框架。 DevTools 试图显示单一的帧时间轴以保持简单,因此它不可能是完美的。出于您的目的,我会查看该 Frames
轨道中屏幕截图的右边缘。右边缘是屏幕更新这些内容的地方。在 Chrome 上,我们称这个时间为 swapBuffers
。 (VSYNC 在技术上是当显示器说“我准备好接受新帧”时,这略有不同)
在 JavaScript 中对此进行测量
不幸的是,您没有完美的工具来实现这一目标。老技术是双rAF,有时减去一些时间。在这一点上你肯定知道有一个新的框架。应用一些 this knowledge ,你可能会非常聪明。但它不会是完美的。例如,长图像解码将延迟合成器发送帧,但主线程现在空闲,VSYNC 将导致它开始一个全新的帧(因此再次调用 rAF)。
Long Task API 可以提供帮助,因为它描述了在主线程上需要花费一段时间的工作类型。但我认为它不会达到我们回答这些问题所需的那种精确度。 Frame Timing 本来有,但由于隐私原因它死了。
TDLR:
使用 timestamp from the input event ,因为它是在合成器接收到输入时获取的。然后使用一些单 rAF、双 rAF 机制,减去一些时间,来估计帧的交付时间。当你有满意的事情时就大喊大叫;我有兴趣。
关于javascript - Chrome DevTools 如何衡量交互响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47170962/