性能分析工具:如何分析Performance中的Main指标?

任务 vs 过程

Main 指标中的任务和过程:

渲染进程中维护了消息队列,如果通过 SetTimeout 设置的回调函数,通过鼠标点击的消息事件,都会以任务的形式添加消息队列中,然后任务调度器会按照一定规则从消息队列中取出合适的任务,并让其在渲染主线程上执行。
Main 指标就记录渲染主线上所执行的全部任务,以及每个任务的详细执行过程。

图上方有很多一段一段灰色横条,每个灰色横条就对应了一个任务,灰色⻓条的⻓度对应了任务的执行时⻓。记录这些任务的细节就是任务的过程。

为了更好的理解,可以把该图形看成是下面 Task 函数的执行过程:

function A(){
    A1()
    A2()
}
function Task(){
    A()
    B()
}
Task()

分析页面加载过程

将报告⻚中的 Main 指标一些关键任务和其执行过程绘制为示意图:

Mian指标

通过上面的图,我们可以看出,加载过程主要分为三个阶段:
导航阶段,该阶段主要是从网络进程接收HTML响应头和HTML响应体。
解析 HTML 数据阶段,该阶段主要是将接收到的 HTML 数据转换为 DOM 和CSSOM。
生成可显示的位图阶段,该阶段主要是利用 DOM 和 CSSOM,经过计算布局、生成层树 (LayerTree)、生成绘制列表 (Paint)、完成合成等操作,生成最终的图片。

导航阶段

导航流程:当你点击了 Performance 上的重新录制按钮之后,浏览器进程会通知网络进程去请求对应的 URL 资源;一旦网络进程从服务器接收到 URL 的响应头,便立即判断该响应头中的content-type 字段是否属于 text/html 类型;如果是,那么浏览器进程会让当前的⻚面执行退出前的清理操作,比如执行 JavaScript 中的 beforunload 事件,清理操作执行结束之后就准备显示新⻚面了,这包括了解析、布局、合成、显示等一系列操作。
传送门:《导航流程:从输入 URL 到⻚面展示,这中间发生了什么?》

第一个阶段的任务图形:

任务执行过程:

  1. 该任务的第一个子过程就是 Send request,该过程表示网络请求已被发送。然后该任务进入了等待状态。
  2. 接着由网络进程负责下载资源,当接收到响应头的时候,该任务便执行 ReceiveRespone 过程,该过程表示接收到 HTTP 的响应头了。
  3. 接着执行 DOM 事件:pagehide、visibilitychange 和 unload 等事件,如果你注册了这些事件的回调函数,那么这些回调函数会依次在该任务中被调用。
  4. 这些事件被处理完成之后,那么接下来就接收 HTML 数据了,这体现在了 Recive Data过程,Recive Data 过程表示请求的数据已被接收,如果 HTML 数据过多,会存在多个Receive Data 过程。
    等所有的数据都接收完成之后,渲染流程就会执行另外一个任务,Finish Load过程,表示网络请求已经完成。

    解析 HTML 数据阶段

    这个阶段的主要任务就是通过解析 HTML 数据、解析 CSS 数据、执行 JavaScript 来生成 DOM 和 CSSOM。

任务执行过程:

  1. 在parseHTML的过程中,如果解析到了script标签,那么便进入了脚本执行过程,也就是图中的Evalute Script.
  2. 我们知道,要执行一段脚本我们需要首先编译该脚本,于是在 Evalute Script 过程中,先进入了脚本编译过程,也就是图中的 Complie Script。脚本编译好之后,就进入程序执行过程,执行全局代码时,V8 会先构造一个 anonymous 过程,在执行 anonymous过程中,会调用 setNewArea 过程,setNewArea 过程中又调用了 createElement,由于之后调用了 document.append 方法,该方法会触发 DOM 内容的修改,所以又强制执行了 ParserHTML 过程生成的新的 DOM。
  3. DOM 生成完成之后,会触发相关的 DOM 事件,比如典型的 DOMContentLoaded,还有 readyStateChanged。
    DOM生成之后,ParseHTML过程继续计算样式表,也就是Reculate Style,这就是生成CSSOM的过程。关于Reculate Style过程,传送门:《渲染流程(上):HTML、CSS 和 JavaScript,是如何变成⻚面的?》

    生成可显示位图阶段

    生成了 DOM 和 CSSOM 之后,就进入了第三个阶段:生成⻚面上的位图。通常这需要经历布局 (Layout)、分层、绘制、合成等一系列操作

在生成完了 DOM 和 CSSOM 之后,渲染主线程首先执行了一些 DOM 事件,诸如 readyStateChange、load、pageshow。
显示流程大致执行过程:

  1. 首先执行布局,这个过程对应图中的Layout。
  2. 然后更新层树 (LayerTree),这个过程对应图中的 Update LayerTree。
  3. 有了层树之后,就需要为层树中的每一层准备绘制列表了,这个过程就称为 Paint。
  4. 准备每层的绘制列表之后,就需要利用绘制列表来生成相应图层的位图了,这个过程对应图中的 Composite Layers。
    接下来主线程会将合成的任务完全交给合成线程来执行;也可以对照着Composite、Raster和GPU这三个指标来分析:

结合渲染流水线和上图,我们再来梳理下最终图像是怎么显示出来的。

  1. 首先主线程执行到Composite Layers过程之后,便会将绘制列表等信息提交给合成线程,合成线程的执行记录可以通过Compositor 指标来查看
  2. 合成线程维护了一个 Raster 线程池,线程池中的每个线程称为 Rasterize,用来执行光栅化操作,对应的任务就是 Rasterize Paint。
  3. 当然光栅化操作并不是在 Rasterize 线程中直接执行的,而是在 GPU 进程中执行的,因此 Rasterize 线程需要和 GPU 线程保持通信。
  4. 然后 GPU 生成图像,最终这些图层会被提交给浏览器进程,浏览器进程将其合成并最终显示在⻚面上。

    通用分析流程

    通过对 Main 指标的分析,我们把导航流程,解析流程和最终的显示流程都串起来了,通过
    Main 指标的分析,我们对⻚面的加载过程执行流程又有了新的认识,虽然实际情况比这个
    复杂,但是万变不离其宗,所有的流程都是围绕这条线来展开的,也就是说,先经历导航阶
    段,然后经历 HTML 解析,最后生成最终的⻚面。

此文章为5月Day7学习笔记,内容来源于极客时间《浏览器原理》,学习使我快乐,每天进步一点点💪💪

豪猪
4 声望4 粉丝

undefined