从B站出发,用Chrome devTools performance分析页面如何渲
发布时间: 2023-07-11

页面是如何渲染的?通常会得到“解析 HTML、css 合成 Render Tree,就可以渲染了”的回答。但是具体都做了些什么,却很少有人细说,我们今天就从 Chrome 的性能工具开始,具体看看一个页面是如何进行渲染的,以及进行页面优化时需要关注哪些指标。

以“老二次元”网站 bilibili 为例,我们将通过分析 performance 面板,串联起 Chrome 页面渲染流程,以及页面的部分量化指标的含义,来看页面具体是如何渲染的。

获取performance数据

首先,打开Chrome devTools, 选择 performace面板,点击录制按钮开始录制。

之后为了防止我们分析页面时出现无关的干扰,我们通过以下步骤降低干扰项:

打开 Chrome 无痕模式。

关闭所有在 Chrome 无痕模式下启用的拓展(如果有的话)。

在地址栏输入 面板,点击录制按钮。

在已经录制的情况下,地址栏回车,请求 B 站,大概 10s 后,停止录制。

我们从上到下,将图分成以下几块,如下图所示:

展开全文

控制面板

概览面板

网络面板

Web Vitals

线程面板

内存面板

聚合面板

控制面板

控制面板有 4 部分内容,分别为:

disable java samples:启用后会隐藏一些 JS 调用栈的展示。在一些性能较弱的设备例如移动端上,可以开启这项功能。

Network:可以用来模拟各种网络状况。

enableadvanced paint instrumention (slow):启用后 paint 面板会显示与绘制相关事件的更详细的信息。

CPU:可以用来模拟不同的 CPU 性能。

disable java samples:启用后会隐藏一些 JS 调用栈的展示。在一些性能较弱的设备例如移动端上,可以开启这项功能。

Network:可以用来模拟各种网络状况。

enableadvanced paint instrumention (slow):启用后 paint 面板会显示与绘制相关事件的更详细的信息。

CPU:可以用来模拟不同的 CPU 性能。

概览面板

概览面板是各项指标的一个概览,包含了 FPS 帧数、CPU 占用、NET 情况、内存使用情况等。

简单举个例子,比如 FPS 帧数可以直观的看出 FPS 的高低,绿色代表低的部分。而 CPU 栏的黄色代表着 js,紫色代表计算样式和布局,绿色代表绘制。

网络面板

网络面板用于展示正在请求中的各部分的组成情况。

Web vitals

Web vitals 是网站的 Web 体验指标,其中包括 LCP(最大内容绘制)、FID(首次输入延迟)、cls (累计布局偏移)等。

线程面板

线程面板用于展示渲染当前页面所使用到的线程,包含有 Main 线程、GPU 线程、Raster 线程、Chrome_ChildIOThread、Compositor 线程等等。其中 Main 线程,就是我们平时说的大部分 js 的运行环境,即主线程。

内存面板

展示 js 内存、GPU 内存、节点数、监听事件数的变化。

聚合面板

当点击主线程中的火焰图时,此面板会显示显示具体包含执行时间、执行组成、调用栈等等的信息集合。

Chrome是如何渲染页面的?

第一个请求

以第一个请求为例,我们来具体看一下 Chrome 是如何进行页面渲染的?依然是以对 中水平箱线图开始的部分。

其中两边横线中间深浅色方框的部分是水平箱线图,是用来展示某部分在整体中的比例关系。比如我们看到这个长长的箱型图,通过直观感受,就能知道对前面一部分横线挺长的,蓝色部分里浅色部分很长,深色的短,右边的横线几乎看不到。那这些又分别能展示什么信息?

首先,点开箱型图最下方的聚合面板(Summary),上面赫然写着:此乃页面源。欲求小破站, 终生皆让我……耗时一秒半。

然后在 Network tab 里查看该请求的 timing 部分,可以得到如下图:

这里的各个部分分别代表:

Queueing(排队):浏览器会在一些情况下让请求排队等待,比如这个请求的优先级不高,有更高优先级的请求存在;在使用 用于在磁盘缓存中分配空间。

Stalled(停顿):它可能会因为上述排队中的任何原因而停顿。

DNS lookup(DNS 查询):解析这个域名的IP地址。需要注意的是,当我们多次访问同一域名时,这部分不会出现在 timing 中。

Initial connection(初始连接):浏览器建立连接,包括 tcp 三次握手、重试以及协商 SSL。图中的紫色部分,就代表了在初始连接过程中的 SSL 协商部分。

Request sent(发送请求):正在发送请求

Waiting (TTFB) 等待第一字节时间:浏览器在等待第一个响应的字节,TTFB 即 Time To First Byte。这个时间包括一个往返的延迟和服务准备响应的时间之和。

Content Download (内容下载):浏览器正在接收响应,浏览器可以通过网络或者 serviceWorker 来直接接收。这个值是读取响应体的总时间。由于网络不佳或者浏览器正在忙于执行其他工作而延迟了对响应体的读取,读取的时间可能会比预期的要长。

Queueing(排队):浏览器会在一些情况下让请求排队等待,比如这个请求的优先级不高,有更高优先级的请求存在;在使用 用于在磁盘缓存中分配空间。

Stalled(停顿):它可能会因为上述排队中的任何原因而停顿。

DNS lookup(DNS 查询):解析这个域名的IP地址。需要注意的是,当我们多次访问同一域名时,这部分不会出现在 timing 中。

Initial connection(初始连接):浏览器建立连接,包括 tcp 三次握手、重试以及协商 SSL。图中的紫色部分,就代表了在初始连接过程中的 SSL 协商部分。

Request sent(发送请求):正在发送请求

Waiting (TTFB) 等待第一字节时间:浏览器在等待第一个响应的字节,TTFB 即 Time To First Byte。这个时间包括一个往返的延迟和服务准备响应的时间之和。

Content Download (内容下载):浏览器正在接收响应,浏览器可以通过网络或者 serviceWorker 来直接接收。这个值是读取响应体的总时间。由于网络不佳或者浏览器正在忙于执行其他工作而延迟了对响应体的读取,读取的时间可能会比预期的要长。

这里相信已经有小伙伴注意到了,当浏览器忙于其他事情时也会让读取时间变长。也就是说,当你的 js 把主线程长期占据的时候,就会影响 content download。

下图是 Network 下的对应资源的 waterfall:

现在我们回到最开始说的各色横条上,在水平箱线图中左上角的深蓝色小方块代表着这个请求有着更高的优先级。遇到有浅蓝色的,则表示较低优先级。同时左边横线对应 Network 面板中显示的 Request Sent之前的所有事情的时间。浅色的 bar对应 Network 中 Request Sent 和 Waiting(TTFB)的时间。深色的 bar对应 Network中Content Download 的时间。右边的横线表示等待主线程所花费的时间,在 Network 面板中没有体现。

此外,可能还有些同学注意到,在蓝色箱线图上面还可以看到还有几个灰色的箱线图。不是说 是页面的第一个请求吗,难道它之前还有请求?

事实上,这个灰色箱线图相当于上一个页面的结束。如果我们是通过重新录制的方式记录 performance,那就会经历页面刷新的过程。而这几个灰色的其实就是页面刷新 unload 时发起的,是 bilibili 用来记录页面卸载时的一些数据。

说回到箱线图,可以看到在 summary 中显示 Duration 1.08 s (822.88 ms Network transfer + 260.20 ms resource loading)。这个的意思是 260ms 的时间是在 resource loading ,这里resource loading所花费的时间其实就是箱线图右侧的那条横线,等待主线程的时间。

而在 main 进程中,有横线结束的地方,可以看到解码的数据 138,933 Bytes。

这里就出现了几个问题:为什么Encode Data 33

微信