朝着更出色的响应能力指标迈进

了解我们对响应能力的衡量想法,并向我们提供反馈。

Annie Sullivan
Annie Sullivan
Hongbo Song
Hongbo Song
Nicolás Peña Moreno
Nicolás Peña Moreno

<ph type="x-smartling-placeholder">

Chrome 速度指标团队致力于更深入地了解 响应用户输入。我们想和大家分享一些改善响应指标的想法, 听取您的反馈。

本博文将涵盖两个主要主题:

  1. 查看我们当前的响应指标“First Input Delay (FID)”,并说明我们选择 FID 的原因 而不是某些替代方案。
  2. 介绍我们考虑的一些改进措施,这些改进措施应该能够更好地捕获端到端 各个事件的延迟时间这些改进还旨在 全面了解网页在整个生命周期内的整体响应情况。

什么是 First Input Delay?

首次输入延迟 (FID) 指标用于衡量浏览器启动所需的时间 处理网页上的首次用户互动具体来说,它衡量的是 用户与设备互动的时间,以及浏览器能够实际 开始处理事件处理脚本。FID 仅针对点按和按键操作进行测量,这意味着 仅考虑以下事件的首次发生:

  • click
  • keydown
  • mousedown
  • pointerdown(仅当其后跟 pointerup 时)

下图展示了 FID:

First Input Delay
衡量从发生输入到可以处理输入的时间

FID 不包括运行这些事件处理脚本所用的时间,也不包括浏览器完成的任何工作 更新屏幕。它测量主线程在启动前处于忙碌状态的时间 使你有机会处理输入。这种阻塞时间通常是由长时间运行的 JavaScript 任务导致的, 因为这些操作不能随时停止,所以必须先完成当前任务, 开始处理输入。

我们为何选择 FID?

我们认为,衡量实际用户体验非常重要,这样可以确保 该指标会给用户带来真正的好处。我们之所以选择衡量 FID,是因为它代表了 会在用户决定与刚刚加载的网站互动时,提供部分用户体验。 FID 捕获了用户必须等待才能看到其响应的一段时间。 用户与网站的互动。换言之,FID 是用户等待时长的下限 互动之后

总阻塞时间 (TBT)可交互时间 (TTI) 等其他指标均基于 长任务,并且像 FID 一样, 测量加载期间主线程的阻塞时间。由于这些指标可以在 和实验室,许多开发者都问我们为什么不偏好其中一个参数而不是 FID。

导致这种情况的原因有多种。最重要的原因可能在于 直接衡量用户体验所有这些指标都会衡量 JavaScript 在网页和 页面。虽然长时间运行的 JavaScript 确实会导致网站出现问题,但这些任务并不会 在发生网页互动时,如果用户未与网页互动,则用户体验必定会受到影响。 网页的 TBT 和 TTI 得分可能很高,但感觉很慢,或者在感觉时得分很低 速度快。根据我们的经验,这些间接衡量带来了适合 某些网站,但不适用于大多数网站。简而言之,耗时较长的任务和 TTI 并非以用户为中心 会成为这些更弱的候选对象。

虽然实验室测量很重要,但 不可或缺的诊断工具,但网站的用户体验。通过使用 以用户为中心的指标,可反映真实的用户条件 能够提供有意义的体验我们决定从这种体验开始入手, 但我们知道这部分并不能代表完整的体验正因如此, 。

<ph type="x-smartling-placeholder">

针对现场真实用户衡量 TTI 是有问题的,因为它发生在网页中很晚 加载。在计算 TTI 之前需要 5 秒的网络静默期。在本实验中, 当您拥有所需的所有数据时,可以选择卸载页面,但事实并非如此 并实时监控真实用户用户可以选择离开网页或与网页互动: 。特别是,用户可能会选择离开需要很长时间才能加载的网页, 在这种情况下,系统不会记录准确的 TTI。我们在 Chrome 中针对真实用户测量 TTI 发现只有大约一半的网页加载到达 TTI。

我们正在考虑哪些改进?

我们希望开发一项新指标,既能扩大当前 FID 衡量的指标范围,又能保持 与用户体验的紧密联系

我们希望新指标能够:

  1. 考虑所有用户输入(而不仅仅是第一次输入)的响应速度
  2. 拍摄每个活动的完整时长(而不仅仅是延迟)。
  3. 将作为同一逻辑用户互动的一部分发生的事件组合在一起,并定义 将互动的延迟时间视为其所有事件的时长上限。
  4. 为网页上发生的所有互动创建总体得分 生命周期

要获得成功,我们应该有信心地告诉您,如果某个网站在这一方面得分很低, 新指标,但对用户互动的响应速度不够快。

完整记录活动时长

第一个显而易见的改进是尝试捕获更广泛的事件的端到端延迟时间。如 即 FID 仅捕获输入事件的延迟部分。它不会考虑 浏览器实际处理事件处理脚本所用的时间。

事件生命周期包含不同的阶段,如下图所示:

五个步骤
事件的生命周期

以下是 Chrome 处理输入的步骤:

  1. 由用户输入发生。发生这种情况的时间即为事件的 timeStamp
  2. 浏览器会执行点击测试,以确定哪个 HTML 框架(主框架或某个 iframe)发生事件 所属的项目。然后,浏览器将事件发送到负责 该 HTML 框架。
  3. 渲染程序接收事件并将其加入队列,以便在它可用时 操作。
  4. 渲染程序通过运行其处理程序来处理事件。这些处理程序可将其他 异步工作(例如 setTimeout 和提取),属于输入处理的一部分。但在 此时,同步工作就完成了
  5. 屏幕上会绘制一个帧,以反映事件处理脚本的运行结果。请注意, 事件处理脚本加入队列的任何异步任务可能仍未完成。

上述第 (1) 步和第 (3) 步之间的时间间隔即是事件的延迟时间,即 FID 衡量的延迟时间。

上述第 (1) 步和第 (5) 步之间的间隔时间即是事件的时长。这个新指标就是 衡量。

事件的持续时间包括延迟,但也包括事件处理脚本中发生的工作 以及浏览器在这些处理程序运行后绘制下一帧所需完成的工作。通过 目前,Event Timing API 中可通过 条目的时长 属性。

理想情况下,我们还希望捕获由 事件触发的异步工作。但问题在于 想要正确定义由事件触发的异步工作非常困难。如 例如,开发者可以选择在事件处理脚本上开始播放一些动画,并使用 setTimeout 开始播放此类动画如果我们捕获了在处理程序上发布的所有任务,动画会延迟 持续到动画播放期间的完成时间。我们认为,有必要调查 有关如何使用启发法捕获异步工作以及应完成的工作的选项 尽快。不过,我们要格外小心,因为我们不想对工作造成不利影响 需要很长时间才能完成因此,我们最初的工作将着眼于第 5 步, 终点:它只会考虑同步工作以及 此类工作已完成。也就是说,我们不会应用启发法来猜测 在我们的初始工作的第 4 步中异步启动。

值得注意的是,在许多情况下,工作应同步执行。事实上,这可能是 不可避免,因为事件有时会逐个分派,而事件处理脚本需要 将要按顺序执行尽管如此,我们仍然会遗漏重要的工作,例如触发 提取数据或依赖在下一个 requestAnimationFrame 回调中完成的重要工作, 示例。

将事件分组为互动

第一步是将指标测量从“延迟时间”延长到“时长”,不过它仍然适用。 在指标方面存在一个严重的缺口:它侧重于单个事件,而不是 与网页互动

单次用户互动可触发许多不同的事件,并分别衡量 但它们都无法让用户清楚地了解用户体验。我们希望确保我们的指标 捕获了用户在点按、按下按键时必须等待响应的总时长, 尽可能准确地进行滚动和拖动因此,我们引入了 互动次数,以衡量每次互动的延迟时间。

互动类型

<ph type="x-smartling-placeholder">

下表列出了我们要定义的四种互动,以及 其关联。请注意,这与之前触发的所有事件 在此类用户互动发生时分派。例如,当用户滚动屏幕时,滚动事件 但其发生在屏幕更新以反映滚动之后,因此 请将它视为互动延迟时间的一部分

互动 开始 / 结束 桌面事件 移动设备事件
键盘 已按下按键 keydown keydown
keypress keypress
密钥已释放 keyup keyup
点按或拖动 点按开始或拖动开始 pointerdown pointerdown
mousedown touchstart
向上或拖动末尾 pointerup pointerup
mouseup touchend
click mousedown
mouseup
click
滚动 不适用
每种互动类型的 DOM 事件。

FID 目前涵盖上面列出的前三项互动(键盘、点按和拖动)。 对于新的响应能力指标,我们还希望包含滚动,因为滚动是 是网页对用户的响应速度的一个重要方面。

请注意,这些互动都包含两个部分:当用户按鼠标、手指或按键时 以及把它抬起来时我们需要确保指标不会计入用户花费的时间 作为网页延迟时间的一部分,请将手指放在这两项操作之间!

键盘

键盘交互包含两个部分:用户按下按键和松开按键。 有三个与此用户互动相关联的事件:keydownkeyupkeypress。 下图展示了键盘的 keydownkeyup 延迟和时长 互动:

键盘互动
具有不相交事件持续时间

在上图中,时长是不相交的,因为来自 keydown 更新的帧是 在 keyup 发生之前显示,但不一定始终如此。此外,请注意 自上一步骤后,在渲染器进程的任务过程中,可以呈现帧。 需要在渲染程序进程之外完成。

keydownkeypress 在用户按下按键时发生,而 keyup 则会在用户按下按键时发生 用户释放密钥。通常,主要内容更新会在按键时进行:文本 或应用修饰符效果。尽管如此,我们仍希望 在极少数情况下,keyup 也会显示有趣的界面更新,因此我们需要了解 所用的总时间。

为了捕获键盘互动所用的总时间,我们可以计算出 keydownkeyup 事件的时长上限。

<ph type="x-smartling-placeholder">

这里还有一种值得注意的极端情况:用户可能按下按键,然后 需要一段时间才会释放在这种情况下, vary。在 在这些情况下,我们认为每个 keydown 只有一次互动,该互动不一定 相应的 keyup

点按

另一个重要的用户互动是用户点按或点击网站。类似于 keypress,有些事件在用户按下时触发,还有一些事件在用户按下时触发,如 请注意,与点按相关联的事件在桌面设备上与 。

对于点按或点击,释放操作通常是触发大多数反应的释放操作,但是, 与键盘互动一样,我们希望捕获完整的互动。在这个示例中, 这一点非常重要,因为在点按时进行一些界面更新其实并不罕见。

我们想同时列出所有这些活动的活动持续时间,但因为其中很多活动存在重叠 我们只需要测量 pointerdownpointerupclick 即可覆盖所有 互动

我们最初的想法是使用 pointerdownpointerup 事件,并假设它们 涵盖我们感兴趣的所有时长遗憾的是,事实并非如此, 显示的内容。尝试在移动设备上或移动设备上打开此网站 点按显示“Click me”的位置。此网站会触发浏览器点按 延迟。用户能看到 pointerdownpointeruptouchend 会快速分派,而 mousedownmouseupclick 会等待延迟才会被分派。这意味着,如果只查看 在 pointerdownpointerup 处,我们会错过合成事件的时长, 尺寸过大,应将其包含在内。因此我们要测量 pointerdownpointerupclick 以涵盖完整互动。

拖动

我们还决定加入拖动操作,因为它具有类似的关联事件,而且通常 会导致网站界面发生重要更新。但对于我们的指标,我们打算仅考虑拖延期开始 和拖动结束部分 - 拖动操作的初始部分和最后部分。这样更便于推断 而且延迟时间与考虑的其他互动相当。这是 这与我们排除 mouseover 等连续事件的决定一致。

我们也不考虑通过拖放操作实施拖动操作 因为它们

滚动

滚动浏览是与网站互动的最常见形式之一。对于这个新指标 比如衡量用户首次滚动互动的延迟时间具体而言,我们 关注浏览器对于用户请求滚动这一事实所做出的初步反应。我们将 不会覆盖整个滚动体验也就是说,滚动会生成许多帧, 我们将注意力集中在初始帧上,这是由于滚动操作而产生的。

为什么只针对第一种情况呢?首先,后续帧可能会通过单独的平滑度进行捕获 提案。 也就是说,当系统向用户显示第一个滚动结果后,其余结果应以 来判断滚动体验的流畅性因此,我们认为 以便更好地捕获这些内容因此,与 FID 一样,我们选择坚持独立的用户体验: 这些体验具有与之相关的明确时间点,并且我们可以轻松计算这些体验 延迟时间整体滚动是一种连续的体验,因此我们并不打算衡量所有 该指标。

那么,为什么要测量滚动次数呢?我们在 Chrome 中收集的滚动性能数据显示,滚动 速度通常很快尽管如此,我们仍然希望将初始滚动延迟时间纳入新指标中 。首先,滚动速度之所以很快,是因为我们对其进行了充分的优化, 非常重要不过,网站仍有办法绕过一些 所有功能。Chrome 中最常见的一种方式是强制在主要 线程。因此,我们的指标应该能够判断这种情况何时发生并导致滚动性能不佳 。其次,滚动操作非常重要,不能忽略。我们担心,如果我们排除 就会出现一个大盲点,在没有网站的情况下,滚动性能可能会随着时间的推移而下降 以便开发者正确识别

当用户滚动时,系统会分派多个事件,例如 touchstarttouchmovescroll。除了滚动事件之外,这在很大程度上取决于 滚动:在移动设备上用手指滚动时,系统会分派触摸事件,而滚轮 事件发生。初始滚动后会触发滚动事件 已完成。一般来说,没有 DOM 事件会阻止滚动,除非网站使用非被动 事件监听器。所以我们将滚动视为与 DOM 分离 事件总数。我们想要衡量的是,从用户操作开始, 滚动手势,直到显示滚动事件的第一帧为止。

如何定义互动的延迟时间?

如上所述,包含“向下”键的互动和“向上”都需要考虑 以免归因于用户按住手指的时间。

对于这些类型的互动,我们希望延迟时间包含所有事件的持续时间 及其关联。由于每次“观看”事件发生的时间和“向上”部分互动可以 重叠,可达到此上限的互动延迟时间的最简单定义就是“最大时长” 任何相关事件的名称再次参考之前的键盘示意图,这个 keydown 时长,因为它比 keyup 长:

键盘互动
突出显示了时长上限

keydownkeyup 的时长也可能会重叠。例如,当帧中的 为这两个事件呈现相同的内容,如下图所示:

键盘互动
在同一帧中按下和松开

使用最大值的方法各有利弊,我们很想知道 您的反馈

  • Pro:这与我们打算衡量滚动的方式一致,因为它仅测量单次 持续时间值。
  • Pro:它旨在减少键盘互动等情况下的噪声,此时 keyup 通常 不执行任何操作,并且用户可能按下按键并快速或缓慢释放。
  • Con:无法捕获用户的完整等待时间。例如,它会捕获 (但不能同时执行这两种操作)。

对于滚动(只有一个关联事件),我们希望将其延迟时间定义为 滚动生成第一帧所需的时长。也就是说, 是第一个 DOM 事件 timeStamp(如 touchmove,如果使用 手指)足够大,可以触发滚动以及反映滚动的首次绘制操作 情况。

汇总每个网页的所有互动

定义互动的延迟时间后,我们需要计算一个汇总值 可能会发生多次用户互动的情况通过提供汇总值,我们能够:

  • 与业务指标形成关联。
  • 评估与其他性能指标的相关性。理想情况下,我们的新指标 能够给现有指标带来价值。
  • 以易于理解的方式在工具中轻松公开值。

为了执行这种聚合,我们需要解决以下两个问题:

  1. 我们会尝试汇总哪些数据?
  2. 我们如何汇总这些数字?

我们正在探索和评估多个选项。欢迎您就这一汇总发表看法。

一种方法是为互动的延迟时间制定预算,具体延迟时间可能取决于互动类型 (滚动、键盘、点按或拖动)。例如,如果点按预算为 100 毫秒, 那么每次点按的延迟时间为 150 毫秒,那么此互动的超出预算金额将是 50 毫秒。然后,我们可以计算出任意实例 用户互动

另一种方法是计算整个生命周期内互动的平均延迟时间或中位数 页面。因此,如果我们有 80 毫秒、90 毫秒和 100 毫秒的延迟时间,那么 网页的延迟时间为 90 毫秒。我们还可以将“超出预算”的平均或中位数视为 考虑不同的预期互动方式。

这在 Web Performance API 上是什么样的?

Event Timing 缺少什么?

遗憾的是,本博文中介绍的所有想法都无法通过 Event Timing 捕获。 API。特别是,没有简单的方法可了解与给定用户关联的事件 与 API 之间的交互为此,我们建议将 interactionID 添加到 API

Event Timing API 的另一个缺点是,无法衡量滚动 因此我们正在努力实现这些 测量 (通过 Event Timing 或单独的 API)。

你现在可以尝试什么?

目前,仍然可以计算点按/拖动操作和键盘的最大延迟时间 互动。以下代码段会生成这两个指标。

let maxTapOrDragDuration = 0;
let maxKeyboardDuration
= 0;
const observer = new PerformanceObserver(list => {
  list
.getEntries().forEach(entry => {
   
switch(entry.name) {
     
case "keydown":
     
case "keyup":
        maxKeyboardDuration
= Math.max(maxKeyboardDuration,
            entry
.duration);
       
break;
     
case "pointerdown":
     
case "pointerup":
     
case "click":
        maxTapOrDragDuration
= Math.max(maxTapOrDragDuration,
            entry
.duration);
       
break;
   
}
 
});
});
observer
.observe({type: "event", durationThreshold: 16, buffered: true});
// We can report maxTapDragDuration and maxKeyboardDuration when sending
// metrics to analytics.

反馈

如果您有任何想法,请发送电子邮件至 web-vitals-feedback@googlegroups.com 告诉我们!