乐趣区

关于前端:使用-Performance-看看浏览器在做什么

前言

Chrome 浏览器的 Performance 面板为咱们提供了检测页面性能的能力,但其提供的远不止一些性能数据。本文将从工作原理的视角,结合实际工程的录制后果,探一探性能面板向咱们走漏的其余信息。

性能面板

对于面板的性能与应用办法,能够参考这篇文章。本节次要介绍浏览器架构与性能面板的关系。

因为尚未决出最终的规范架构,各大浏览器的实现细节各有不同。这里咱们以 Chrome 的架构为例,对照其架构与性能面板的关系。

由下图咱们能够看到性能面板出现的几个次要线程。性能面板并不蕴含架构中全副的线程,次要还是与页面渲染过程相干的局部。

Network

Network 代表浏览器过程中的网络线程,咱们能够看到时间轴上蕴含了所有的网络申请和文件下载的调用信息,并以不同色彩标识不同类型的资源。

Main

Main 代表渲染过程中的主线程,渲染相干的事件根本都是它来做,脚本执行、款式计算、布局计算、绘制等等。

Compositor & Raster

Compositor 代表渲染过程中的合成线程,Raster 代表渲染过程中的栅格线程。现在浏览器绘制一个页面,能够分为以下几步:

  • 主线程将页面分成若干图层(后文中会提及 Update Layer Tree)
  • 栅格线程别离对每一个层进行栅格化处理
  • 合成线程将栅格化的图块合并成一个页面


咱们能够看到,在性能面板中主线程在最初调用了栅格线程做理论的渲染。

GPU

显然,这部分就是 GPU Process 中的 GPU 线程。

浏览器的工作报告

接下来咱们将大抵从工夫维度,看看浏览器录制下来的「工作报告」。

文档的下载解析

咱们旅途的终点将从点击 Chrome Performance Panel 的 Reload 按钮(形如刷新)开始。以后页面首先进行卸载,随同着几个日志上报,浏览器开始了 index.html 的下载工作。

HTML 文档下载实现后,浏览器开始依照 HTML 规范对 index.html 进行解析,在主线程中将接管到的文本字符串解析为 DOM。咱们能够留神到,HTML 的解析过程并不是零打碎敲,这是因为 HTML 通常还包含了其余内部资源,如图片、CSS、JS 等。这些文件须要通过网络申请或缓存来获取。其中,当 HTML 解析器解析到 <script> 标签时,HTML 文档的解析过程就会停止,转而去加载、解析和执行脚本。因而,从主线程的时间轴能够看出,Parse HTML 的过程是断断续续的。

不同资源的解决

以下解决策略都能够在主线程中看到,然而不同资源的解决条长短差距较大,截图艰难,这里不做出现。

那么浏览器对不同资源的解决策略是怎么的呢?

  • 浏览器下载 HTML 并解析,如果遇到内部 CSS 等资源,就会由 Browser 过程中的 network 线程下载
  • 当 CSS 下载时,HTML 的解析过程能够持续
  • 当解析遇到了内部 Script 标签(不蕴含 async、defer 属性)时,解析进行,直到脚本下载并执行实现

总的来说,浏览器对 HTML 的解析过程不会被 CSS、IMG 等资源的下载阻塞,但脚本的加载和执行会终止 HTML 的解析。这次要是因为 JS 可能会扭转 DOM 的构造,或者是 JS 动静加载其余 JS 再扭转 DOM 等潜在问题。

显然,只管浏览器能够并发几个 network 线程下载资源,但如果仅像上述策略这样解决,当解析到 <script> 时,如果文件较大或者提早较高,可能会产生「脚本独占线程而没有其余资源在下载」的空窗期(idle network)。因而,pre-loader(或者 preload scanner 等叫法)将会在主线程之外,扫描余下的标签,充分利用 network 线程下载其余资源。这种机制能够优化 19% 的加载时长。

脚本的解析执行

对于重业务逻辑的简单中后盾利用而言,脚本带来的性能开销,往往是占次要位置的。咱们从下图的例子就能够看出,去除 beforeunload 之前的卸载,脚本自身的工夫开销占比已过半。解析 HTML 在其次,至于其余款式计算、微工作、垃圾回收等等,倒不是最痛的中央。当然,该例子工程自身重业务逻辑,JavaScript 代码量决定着其高老本。

有时咱们能够思考应用 async 或者 defer 属性来进步页面性能,二者的差别不再赘述。须要专门阐明的是动静增加脚本的状况。如上面示例代码所示,脚本被 append 到文档中后就会开始下载,并且默认和 async 具备一样的行为,即「先加载完的先执行」。

let script = document.createElement('script');
script.src = "/xxx/a.js";
document.body.append(script);

如果专门设置了 async 属性,则会依照 defer 的行为来,即「先加载到的先执行」。

function loadScript(src) {let script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.body.append(script);
}

// 因为 async = false,所以按程序先执行 big;否则(个别会先)执行 small
loadScript("/xxx/big.js");
loadScript("/xxx/small.js");

从下图中能够看到,调用栈中执行的 appendChild 办法动静增加了 script 脚本,之后很快开始了下载动作。动静加载的脚本实现下载后,又第一工夫开始了脚本执行。

lifecycle 和 paint timing

下图展现的是文章中提及的页面生命周期流程图。本节咱们联合 Performance,对照该图进行察看。

beforeunload

因为 Performance 的录制是在已有页面上进行 reload,所以记录的生命周期从页面的卸载开始。如下图 Main 所示,beforeunload 事件首先被浏览器触发。能够留神到,黄色条 Event: beforeunload 是浏览器本身触发的流动,咱们称之为根流动(Root activities)。

pagehide

从下图中咱们能够留神到,为什么事件的触发程序和下面的生命周期流程图不统一,是 pagehide -> visibilitychange -> unload 呢?事实上,在浏览器之前的设计中,如果页面在卸载阶段可视,visibilitychange 就会在 pagehide 之后触发,正如下图截图中一样。这就使得页面的卸载在不同可视状况下,有着不统一的生命周期与事件程序,给开发者带来复杂性。

在将来新版本浏览器中,卸载阶段的事件程序会进行对立,目前进度在这一 issue 下。也正因为这部分的调整,unload 曾经不倡议在代码实现中应用了。

first paint

首先辨别下以下两个工夫点:

  • first paint:指的是首个像素开始绘制到屏幕上的机会,例如一个页面的背景色
  • first contentful paint:指的是开始绘制内容的机会,如文字或图片

从 Performance 中,咱们能够看出首次绘制的一系列动作(有些过程啪的一下很快啊,截图就省了):

  1. CSS 加载实现
  2. Parse Stylesheet:解析样式表,构建出 CSSOM
  3. Recalculate Style:从新计算款式,确定款式规定
  4. Layout:依据计算结果进行布局,确定元素的大小和地位
  5. Update Layer Tree:更新渲染层树
  6. Paint:依据 Layer Tree 绘制页面(地位、大小、色彩、边框、暗影等)
  7. Composite Layers:组合层,浏览器将图层合并后输入到屏幕

Layout 之后的过程很快,这里放大些倍数来查看:

DOMContentLoaded

DOMContentLoaded 示意 HTML 曾经齐全被加载和解析,当然样式表、图片等资源还不肯定曾经实现加载。从下图中能够看到,通过多段 HTML 解析后,DCL 之后就没有其余的 Parse HTML 了。

pageshow/load

因导航而使得浏览器在窗口内出现文档时,浏览器会在 window 上触发 pageshow 事件,具体的机会可参考这里。不仅如此,当页面是首次加载时,pageshow 事件会在 load 事件后触发。

那么回到 Performance 的时间轴,从下图咱们能够看到,在红色虚线(标记着 load)之后,浏览器触发了 pageshow 事件,也就是上文提及的根流动。

工作与性能问题

比拟惋惜的是,Performance 还无奈清晰的看出 Event Loop。下图中灰色的 Task 并不是指宏工作,其代表的是「以后主线程繁忙,无奈响应用户交互」;Run Microtasks 则的确是在一次工作的开端执行的微工作。当咱们点开调用栈察看时,能够看到源码中的回调函数以及对应的源码地位。

通过 Task 能够定位性能呈现问题的中央。RAIL 模型通知咱们须要重点关注占用 CPU 超出 50ms 的简单工作,以提供连贯的交互体验。当然,这里更多的是对交互阶段的响应的要求,而不肯定是对初始加载阶段的要求。

总结

本文从工作原理的视角,结合实际工程的录制后果,进行了一次实际对理论知识的测验。Performance 不仅是性能剖析工具,还是探索浏览器工作原理的小霸王学习机。总的来说,浏览器的工作是空虚且简单的,与咱们打工人的摸鱼日常造成了比照,还是须要进一步加深学习与思考呀。

参考链接

[1] Measure performance with the RAIL model
[2] Get Started With Analyzing Runtime Performance
[3] Inside look at modern web browser
[4] JavaScript Start-up Performance
[5] How browsers work
[6] How the Browser Pre-loader Makes Pages Load Faster

文章可随便转载,但请保留此原文链接。
十分欢送有激情的你退出 ES2049 Studio,简历请发送至 caijun.hcj@alibaba-inc.com。

退出移动版