性能分析工具:如何分析Performance中的Main指标?
任务 vs 过程
Main 指标中的任务和过程:
渲染进程中维护了消息队列,如果通过 SetTimeout 设置的回调函数,通过鼠标点击的消息事件,都会以任务的形式添加消息队列中,然后任务调度器会按照一定规则从消息队列中取出合适的任务,并让其在渲染主线程上执行。
Main 指标就记录渲染主线上所执行的全部任务,以及每个任务的详细执行过程。
图上方有很多一段一段灰色横条,每个灰色横条就对应了一个任务,灰色⻓条的⻓度对应了任务的执行时⻓。记录这些任务的细节就是任务的过程。
为了更好的理解,可以把该图形看成是下面 Task 函数的执行过程:
function A(){
A1()
A2()
}
function Task(){
A()
B()
}
Task()
分析页面加载过程
将报告⻚中的 Main 指标一些关键任务和其执行过程绘制为示意图:
通过上面的图,我们可以看出,加载过程主要分为三个阶段:
导航阶段,该阶段主要是从网络进程接收HTML响应头和HTML响应体。
解析 HTML 数据阶段,该阶段主要是将接收到的 HTML 数据转换为 DOM 和CSSOM。
生成可显示的位图阶段,该阶段主要是利用 DOM 和 CSSOM,经过计算布局、生成层树 (LayerTree)、生成绘制列表 (Paint)、完成合成等操作,生成最终的图片。
导航阶段
导航流程:当你点击了 Performance 上的重新录制按钮之后,浏览器进程会通知网络进程去请求对应的 URL 资源;一旦网络进程从服务器接收到 URL 的响应头,便立即判断该响应头中的content-type 字段是否属于 text/html 类型;如果是,那么浏览器进程会让当前的⻚面执行退出前的清理操作,比如执行 JavaScript 中的 beforunload 事件,清理操作执行结束之后就准备显示新⻚面了,这包括了解析、布局、合成、显示等一系列操作。
传送门:《导航流程:从输入 URL 到⻚面展示,这中间发生了什么?》
第一个阶段的任务图形:
任务执行过程:
- 该任务的第一个子过程就是 Send request,该过程表示网络请求已被发送。然后该任务进入了等待状态。
- 接着由网络进程负责下载资源,当接收到响应头的时候,该任务便执行 ReceiveRespone 过程,该过程表示接收到 HTTP 的响应头了。
- 接着执行 DOM 事件:pagehide、visibilitychange 和 unload 等事件,如果你注册了这些事件的回调函数,那么这些回调函数会依次在该任务中被调用。
这些事件被处理完成之后,那么接下来就接收 HTML 数据了,这体现在了 Recive Data过程,Recive Data 过程表示请求的数据已被接收,如果 HTML 数据过多,会存在多个Receive Data 过程。
等所有的数据都接收完成之后,渲染流程就会执行另外一个任务,Finish Load过程,表示网络请求已经完成。解析 HTML 数据阶段
这个阶段的主要任务就是通过解析 HTML 数据、解析 CSS 数据、执行 JavaScript 来生成 DOM 和 CSSOM。
任务执行过程:
- 在parseHTML的过程中,如果解析到了script标签,那么便进入了脚本执行过程,也就是图中的Evalute Script.
- 我们知道,要执行一段脚本我们需要首先编译该脚本,于是在 Evalute Script 过程中,先进入了脚本编译过程,也就是图中的 Complie Script。脚本编译好之后,就进入程序执行过程,执行全局代码时,V8 会先构造一个 anonymous 过程,在执行 anonymous过程中,会调用 setNewArea 过程,setNewArea 过程中又调用了 createElement,由于之后调用了 document.append 方法,该方法会触发 DOM 内容的修改,所以又强制执行了 ParserHTML 过程生成的新的 DOM。
DOM 生成完成之后,会触发相关的 DOM 事件,比如典型的 DOMContentLoaded,还有 readyStateChanged。
DOM生成之后,ParseHTML过程继续计算样式表,也就是Reculate Style,这就是生成CSSOM的过程。关于Reculate Style过程,传送门:《渲染流程(上):HTML、CSS 和 JavaScript,是如何变成⻚面的?》生成可显示位图阶段
生成了 DOM 和 CSSOM 之后,就进入了第三个阶段:生成⻚面上的位图。通常这需要经历布局 (Layout)、分层、绘制、合成等一系列操作
在生成完了 DOM 和 CSSOM 之后,渲染主线程首先执行了一些 DOM 事件,诸如 readyStateChange、load、pageshow。
显示流程大致执行过程:
- 首先执行布局,这个过程对应图中的Layout。
- 然后更新层树 (LayerTree),这个过程对应图中的 Update LayerTree。
- 有了层树之后,就需要为层树中的每一层准备绘制列表了,这个过程就称为 Paint。
- 准备每层的绘制列表之后,就需要利用绘制列表来生成相应图层的位图了,这个过程对应图中的 Composite Layers。
接下来主线程会将合成的任务完全交给合成线程来执行;也可以对照着Composite、Raster和GPU这三个指标来分析:
结合渲染流水线和上图,我们再来梳理下最终图像是怎么显示出来的。
- 首先主线程执行到Composite Layers过程之后,便会将绘制列表等信息提交给合成线程,合成线程的执行记录可以通过Compositor 指标来查看
- 合成线程维护了一个 Raster 线程池,线程池中的每个线程称为 Rasterize,用来执行光栅化操作,对应的任务就是 Rasterize Paint。
- 当然光栅化操作并不是在 Rasterize 线程中直接执行的,而是在 GPU 进程中执行的,因此 Rasterize 线程需要和 GPU 线程保持通信。
然后 GPU 生成图像,最终这些图层会被提交给浏览器进程,浏览器进程将其合成并最终显示在⻚面上。
通用分析流程
通过对 Main 指标的分析,我们把导航流程,解析流程和最终的显示流程都串起来了,通过
Main 指标的分析,我们对⻚面的加载过程执行流程又有了新的认识,虽然实际情况比这个
复杂,但是万变不离其宗,所有的流程都是围绕这条线来展开的,也就是说,先经历导航阶
段,然后经历 HTML 解析,最后生成最终的⻚面。
此文章为5月Day7学习笔记,内容来源于极客时间《浏览器原理》,学习使我快乐,每天进步一点点💪💪
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。