性能指标都是些什么鬼?

本文讲的是性能指标都是些什么鬼?,

原文地址: Performance metrics. What’s this all about?
原文作者: Artem Denysov
译文出自: 掘金翻译计划
本文永久链接: https://github.com/xitu/gold-miner/blob/master/TODO/performance-metrics-whats-this-all-about.md
译者: llp0574
校对者: ppp-man lampui

测量页面的加载性能是一项艰难的任务。因此 Google Developers 正和社区一起致力于渐进式网页指标(Progressive Web Metrics,简称 PWM’s)。

PWM’s 都是些什么,我们为什么需要它们?

先来讲一点关于浏览器指标的历史。

此前我们有两个主要的点(事件)来测量性能:

DOMContentLoaded — 页面加载时触发,但脚本文件刚刚开始执行。

load 事件在页面完全加载后触发,此时用户已经可以使用页面或应用。

举个例子,如果我们看一下 reddit.com 的跟踪时间轴(Chrome 的开发者工具可以帮助我们用蓝色和红色的垂直线来标记那些点),就可以明白为什么这些指标不是那么有用了。


时至今日,我们也可以看到 window.onload 并没有像以前那样真实反映出用户的感知。

参考:Steve Souders,Moving beyond window.onload() (2013)

确实,DOMContentLoaded 的问题在于解析和执行 JavaScript 的时间,如果脚本文件太大,那么这个时间就会非常长。比如移动设备,在 3G 网络的限制下测量跟踪时间轴,就会发现要花费差不多十秒才能到达 load 点。

另一方面,load 事件太晚触发,就无法分析出页面的性能瓶颈。

所以我们能否依赖这些指标?它们到底给我们提供了什么信息?

而且最主要的问题是,从页面开始加载直至加载完成,用户如何感知这个过程

为什么加载感知会如此重要?可以参考 Chrome Developers 上的一篇文章:Leveraging the Performance Metrics that Most Affect User Experience,再次强调了加载问题。

看一下下方柱状图,X 轴展示了加载时间,Y 轴展示了体验到加载时长在特定时间区间里的用户的相对数量,你就可以明白不是所有用户的体验加载时间都会小于两秒。


因此在我们的试验里,17 秒左右的 load 时间在获取用户感知加载这方面是没有什么价值的。用户在这 17 秒里到底看到了什么?白屏?加载了一半的页面?页面假死(用户无法点击输入框或滚动)?如果这些问题有答案的话:

  1. 可以改善用户体验
  2. 给应用带来更多的用户
  3. 增加产品所有者的利益(用户、消费者、钱)

所以,大家都在尝试解读用户的想法并预测用户在这 17 秒的加载时间里会想些什么。

  1. 它正在运行吗?

我的网页浏览开始了吗(服务器有回应,等等)?
Has my navigation started successfully (the server has responded, etc.)?

  1. 它有用吗?

页面上是否有足够关键的内容使我能够理解?

  1. 它可以使用了吗?

我能不能和页面互动了呢?还是它依旧处于加载状态?

  1. 用户体验良好吗?

是否没有滚动卡顿、动画卡顿、无样式内容闪烁和缓慢的 Web 字体文件加载等问题出现,让我感到惊喜?


如果 DOMContentLoaded 或者 load 指标不能回答这些问题,那么什么指标可以回答?

渐进式网页指标(Progressive Web Metrics)

PWM’s 的指标列表目的在于帮助检测性能瓶颈。除开 load 和 DOMContentLoaded,PWM’s 给开发者提供了更多更详细的关于页面加载的信息。

下面让我们用 reddit.com 的跟踪时间轴来探究一下 PWM’s,并尝试弄明白每个指标的意思。



首次绘制(First Paint,FP)

我曾经说我们只有两个指标,这其实不太准确。(Chrome)开发者工具还给我们提供了一个指标 - FP。这个指标表示页面绘制的时间点,换句话说它表示当用户第一次看到白屏的时间点(下面是 msn.com 的 FP 截屏)。可以在规范说明里阅读更多相关内容。


想弄明白它是如何工作的话,作为例子,我们可以看一下 Chromium 图层的底层原理。


FP 事件在图层进行绘制的时候触发,而不是文本、图片或 Canvas 出现的时候,但它也在列表里给出了一些开发者尝试使用的信息。

但它并不是标准指标,所以测量就变得非常棘手。因此用到了一些不同的 “取巧” 技术,比如:

  • 附加 requestAnimationFrame 使用
  • 捕捉 CSS 资源加载
  • 甚至使用 DOMContentLoaded 和 load 事件(它们的问题之前已经讲过)

但是,尽管做出了这些努力,它仍然不具有太大的价值,因为文本、图片和 Canvas 可能在 FP 事件触发没多久就会进行绘制,而这些则会被诸如页面权重、CSS 或 JavaScript 资源大小等性能瓶颈所影响。

这个指标不属于 PWM 的一部分,但它对于理解下面将要讲到的指标很有帮助。

所以需要其他一些指标来表示真实的内容绘制。

首次内容绘制(First Contentful Paint,FCP)

这是当用户看见一些“内容”元素被绘制在页面上的时间点。和白屏是不一样的,它可以是文本的首次出现,或者 SVG 的首次出现,或者 Canvas 的首次出现等等。

因此,用户可能会产生疑问,它正在运行吗? 页面是否在他(她)键入 URL 并按 enter 键后开始加载了呢?


继续看一下 Chromium,FCP 事件在文本(正在等待字体文件加载的文本不计算在内)、图片、Canvas 等元素绘制期间就已经被触发了。因此,FP 和 FCP 的时间差异可能从几毫秒到几秒不等。这个差别甚至可以从上面的图片中看出来。这就是为什么用一个指标来表示真实的首次内容绘制是有价值的。

你可以从这里阅读所有的规范说明。

FCP 指标如何对开发者产生价值?

如果首次内容绘制耗时太长,那么:

  • 你的网络连接可能有性能问题
  • 资源太过庞大(如 index.html),传输它们消耗太多时间

阅读 Ilya Grigorik 写的 High Performance Browser Networking 了解更多关于网络性能的问题,消除这些因素的影响。


首次有意义绘制(First Meaningful Paint,FMP)

这是指页面主要内容出现在屏幕上的时间点,因此,它有用吗?

主要内容是什么?

  • 博客的标题和文本
  • 搜索引擎的搜索文本
  • 对于电子商务产品来说重要的图片

展示的时候。

但如果展示的是

  • 下拉菜单或类似的东西
  • 无样式内容闪烁(FOUC)
  • 导航条或页面标题

不计算在主要内容之内。

FMP = 最大布局变化时的绘制

基于 Chromium 的实现,这个绘制是使用 LayoutAnalyzer 进行计算的,它会收集所有的布局变化,当布局发生最大变化时得出时间。而这个时间就是 FMP。

你可以从这里阅读所有的规范说明。

FMP 指标如何对开发者产生帮助?

如果主要内容很久都没有展示出来,那么:

  • 太多资源(图片、样式、字体、JavaScript)有较高的加载优先级,因此,它们阻塞了 FMP

我不想重复太多已有的用来提升这些瓶颈的实践方法,给大家留出一些链接:

  • Addy Osmani 的 Preload, Prefetch And Priorities in Chrome
  • Ben Schwarz 的 Critical Request
  • Karolina Szczur 的 The State of the Web
  • Paul Irish 和 Sam Saccone 的 Practical Performance (Polymer Summit 2016)

从这些文章里可以找到所有需要的信息。


视觉上准备好

当页面看上去“接近”加载完成,但浏览器还没有执行完所有脚本文件的状态。


预计输入延迟

这个指标意在估计应用对于用户输入的响应有多流畅。

但在深入研究前,我想通过解释一些术语以便大家在理解上同步。

长任务

浏览器底层将所有用户输入打包在一个任务里(UI 任务),并在主线程中将它们放到一个队列里。除此之外,浏览器还必须在页面上解析、编译和执行 JavaScript 代码(应用任务)。如果每个应用任务要耗费很长时间的话,那么用户输入任务就可能在其他任务结束前受到阻塞。因此它就会延迟与页面的交互,页面行为就会变得卡顿有延迟。

简单来说,长任务就是指耗时大于 50 毫秒的解析、编译和执行 JavaScript 代码块。

你可以从这里阅读所有的规范说明。

长任务 API 已经在 Chrome 里实现,并用作测量主线程的繁忙程度。

回到预计输入延迟,用户会假设页面响应很快,但如果主线程正忙于处理各个长任务,那么就会让用户不满意。对于应用来说,用户体验至关重要,可以从 Measure Performance with the RAIL Model 这篇文章里阅读关于这种类型的性能瓶颈如何进行性能提升。


首次交互

交互 - 它可以使用了吗? 是的,这是当用户看见视觉上准备好的页面时提出的问题,他们希望能与页面产生交互。

首次交互发生需满足以下条件:

  • FMP
  • &&
  • DOMContentLoaded 事件被触发
  • &&
  • 页面视觉完成度在 85%

首次交互 - 这个指标可以拆分成两个指标,首次交互的时间(Time to First Interactive,TTFI)和首次持续交互的时间(Time to First Consistently Interactive,TTCI)。

拆分的原因在于:

  • 当 UI 响应良好时,定义最小程度的交互,但如果响应不好也可以接受
  • 当网站有着完整且令人愉悦的交互,并严格遵循 RAIL 的指导原则时

TTCI

使用逆序分析,从追踪线的尾端开始看,发现页面加载活动保持了 5 秒的安静并且再无更多的长任务执行,得到了一段叫做安静窗口的时期。安静窗口之后及第一个长任务(从安静期结束后开始算)之前的时间就是TTCI

TTFI

这个指标的定义和 TTCI 有一点不同。我们从头至尾来分析跟踪时间轴。在 FMP 发生后应该有 3 秒的安静窗口。这个时间已经足够说明页面对于用户来说是可交互的。但可能会有长任务在这个安静窗口期间或之后开始执行,它们可以被忽略。

长任务 - 距离 FMP 很远执行的任务,并由 250ms 的执行时间期间(信道大小)和在信道大小前后的 1 秒安静期分隔开来。这个示例任务有可能是第三方广告或者分析脚本。

有时长于 250 毫秒的“长任务”会对页面有严重的影响。

比如检测adblock

你可以从这里阅读所有的规范说明。

TTFI 和 TTCI 指标如何对开发者产生帮助?

当线程长时间处于视觉上准备好首次交互中间忙碌状态时

这是其中一个最复杂的瓶颈,并且没有标准方法来修复这类型的问题。它是独立的,而且取决于应用的特定情况。Chrome 开发者工具有一系列文章帮助我们检测运行时的性能问题。


视觉上完成 / 速度指数

视觉上完成是通过页面截图来计算的,并使用速度指数算法来对那些截图进行像素分析。有时候测量是否视觉上完成也是一件棘手的事情。

如果页面里有会发生变化的图片如轮播图,那么获取正确的视觉上完成结果就可能有点挑战了。

速度指数本身表示视觉上完成结果的中值。速度指数的值越小,性能就越好。

视觉上 100% 完成是一个最终点,决定了用户对页面是否感到满意。这个时间也是用来回答问题 - 用户体验良好吗?


总结

上述并不是所有的 PWM,但是最重要的一部分。上面的指标都增加了一些资料链接,帮助我们更好地提升它们,另外,我还想留出一些关于测量这些类型指标的工具链接:

  • Web Pagetest
  • Lighthouse
  • pwmetrics
  • Calibre
  • DevTools Timeline Viewer

P.S. 要获得所有这些指标的结果的话,我推荐使用 Lighthouse 或 pwmetrics。Calibre 和 WPT 都可以运行 Lighthouse,并可以通过扩展提供所有这些指标。

如果你想手动测量性能,有一个原生 API,叫 PerformanceObserver,它可以帮助你实现你的测量目标。

从规范说明里截取的示例:

 
        
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
        
const observer = new PerformanceObserver(list => {
list
.getEntries()
// Get the values we are interested in
.map( ({ name, entryType, startTime, duration }) => {
const obj = {
"Duration": duration,
"Entry Type": entryType,
"Name": name,
"Start Time": startTime,
};
return JSON.stringify(obj, null, 2);
})
// Display them to the console
.forEach( console.log);
// maybe disconnect after processing the events.
observer.disconnect();
});
// retrieve buffered events and subscribe to new events
// for Resource-Timing and User-Timing
observer.observe({
entryTypes: [ "resource", "mark", "measure"],
buffered: true
});

感谢所有工作人员,他们在规范说明、文章和工具上做了很出色的工作!






原文发布时间为:2017年10月19日

本文来自云栖社区合作伙伴掘金,了解相关信息可以关注掘金网站。

你可能感兴趣的:(性能指标都是些什么鬼?)