前端性能优化 — 保姆级 Performance 工具使用指南

2024年 1月 30日 43.4k 0

性能分析一直是前端er们津津乐道的话题;而俗话说得好:工欲善其事,必先利其器;

说到前端性能,就少不了性能分析的利器 —— Performance 😎;我想各位前端小伙伴,在使用 Chrome 浏览器 DevTool 时或多或少都有留意到这个面板吧?

图片图片

今天我们就迈开性能分析的第一步,来探究一下 Performance 这个强大的工具。

文章中提到的 Performance 面板,以 Chrome 118 版本为参考。

Performance 面板

我们打开 Performance 面板:

图片图片

我把 Performance 面板大概划分为操作区、设置区、报告区三块区域:

  • 操作区:主要用于性能分析的开启、关闭、性能报告的上传下载等;
  • 设置区:用于设置性能数据分析期间的各项指标,比如:CPU 运算能力、网络状态等等;
  • 报告区:顾名思义,就是呈现最终性能分析报告的地方。

下面我们先来一起看看操作区的内容。

操作区

观察下图中用红线框起来的部分,这里有几个按钮:

图片图片

录制报告

按钮图片图片的功能大致相同,都是用于记录页面性能数据;

两个按钮点击后都会出现下面这样的弹窗:

图片图片

image.png

不过需要注意的是,这两种录制方式之间有一些不同:

  • 点击图片(Record) 按钮,Chrome 会开始记录交互阶段的性能数据,需要手动点击 Stop 停止录制;
  • 而点击图片(Start Profiling and reload page) 按钮,Chrome 会重新刷新页面并自动开始记录,等到页面完全渲染出来后自动结束记录。

清除报告

录制完成的数据,如果我们不需要了,就可以点击图片(Clear) 按钮来清除数据;

是不是很一目了然呢?

上传/下载报告

当我们的数据录制完成,就可以 点击图片(Save Profile) 按钮来将录制的报告下载保存在本地;

有了下载,当然少不了它的好兄弟上传!

点击图片(Load Profile) 就可以将本地报告再次上传到 Performance 面板中;

报告对比

实际上,我们每次录制的报告都被自动留存起来;

当存在多份性能报告时,还可以通过下拉切换查看不同的报告:

图片图片

这样就能很方便地对比不同时间段的性能报告。

图中用红虚线框起来的部分,就是用于切换报告的下拉框。

Screenshots 和 Memory

在操作区的右边还有两个复选框,Screenshots 和 Memory:

图片图片

Screenshots

当勾选 Screenshots 后,在生成的性能报告中就会多出一栏用于记录页面在加载过程中的每一帧的视觉变化,并生成一系列快照;

并且当鼠标 hover 在这个区域时,就可以查看当前帧的快照:

图片图片

通过查看这些快照,我们就可以了解页面在不同时间点的渲染情况。

Memory

而 Memory 功能则是用于观察页面的内存使用情况随时间的变化。

当勾选 Memory 功能后,在性能报告中就会显示页面的总内存使用量、堆内存使用量以及各种 JavaScript 对象的内存分配情况:

图片图片

同样,当鼠标 hover 在下方不同类型文件占据内存情况的折线图时,就可以查看当前时间点下这些文件使用内存的情况。

垃圾回收

最后,操作区的图片(Collect garbage) 按钮用于手动触发 JavaScript 垃圾回收。

图片图片

image.png

当我们在进行性能测试时,就可以在特定的时间点手动触发垃圾回收,以确保测试结果的准确性。

设置区

在文章前面简单介绍过,设置区主要用于设置性能数据分析期间的各项指标;

下面我们来看看具体可以做哪些设置:

图片图片

Disable JavaScript samples

默认情况下,Chrome 在做性能分析采样时会记录当前 JavaScript 执行的堆栈信息,并在报告区的 Main 部分呈现出来:

如果我们不关注 JavaScript 执行相关的性能,比如:测试在不同网络情况下的代码执行性能、测试渲染性能时;

这种情况下就可以勾选 Disable JavaScript samples 这个选项,从而提高性能分析的效率;

未勾选 Disable JavaScript samples 的情况下,报告区记录了 JavaScript 执行时的堆栈信息 (图中红线框起的部分) :

图片图片

勾选了 Disable JavaScript samples 的情况下,报告区只记录了一些高级事件,比如:Function Call、渲染相关事件等:

图片图片

Enable advanced paint instrumentation

这个选项用于启用高级绘制仪器;当你勾选了这个选项后,Chrome 将记录更详细的绘制信息,包括每个绘制操作的时间、持续时间、绘制区域等。

勾选了 Enable advanced paint instrumentation 后,当鼠标选中报告中 Frames 数据的某一帧时,在下方的面板里就会多出一个 Layers 的选项;

图片图片

我们知道,浏览器在渲染一个页面时会有针对性的对一些效果进行分层,而 Layers 的选项下展示的正是页面的图层树信息:

图片图片

通过观察这些绘制操作的时间和持续时间,就能判断哪些绘制操作占用了较长的时间,可能导致页面渲染缓慢对症下药。

CPU 和 Network

在 CPU 下拉选项中,我们可以通过降低 CPU 的性能,来模拟低性能设备上的页面运行情况;比如移动设备,或者一些比较老旧的计算机;

而 Network 下拉框可以选择不同的网络条件,用于模拟网络不佳的情况下页面的运行情况。

Hardware concurrency

hardware concurrency 选项用于模拟硬件并发性能;勾选这个选项后,我们就可以选择从 1 到最大硬件并发性能水平之间的值,以模拟不同的硬件环境。

通过切换不同的 hardware concurrency 值,可以观察页面在不同硬件并发性能水平下的性能表现;这对于优化页面的并发处理和多线程任务非常有帮助。

硬件并发性能是指处理器(CPU)同时执行多个线程或任务的能力。现代计算机通常具有多核处理器,每个核心都可以同时执行多个线程。硬件并发性能的提高可以显著提升计算机的性能和响应能力。

报告区

接下来就是我们的重头戏,最终性能分析报告呈现的区域;我们之前介绍的操作、设置最终都是为性能报告服务。

我们以掘金首页为例,来看看报告区都有哪些内容。

首先,我们要打开谷歌浏览器的无痕模式;默认快捷键是 Command+Option+N (Mac) 或者 Control+Shift+N (Windows, Linux);

然后打开 掘金首页[1],点击图片(Start Profiling and reload page) 按钮来进行录制;

等待几秒钟后,一份完整的性能报告就呈现出来啦:

图片图片

从上图中可以看出,这份性能报告大概可以分为两块区域:概览区、性能报告区。

而所有的这些性能指标都是基于时间的维度来展示的,因此在性能报告中还有一条贯穿整个报告的时间线。

使用无痕模式是为了避免安装的一些插件对性能测试产生影响。

概览区

首先,概览区的 x 轴就是时间线,而 y 轴展示了几个关键指标:CPU 占用情况、NET 网络请求情况、HEAP 堆内存使用量等;如果勾选了 Screenshots 还会有每一帧的绘制快照。

这些指标会以时间为顺序,通过图表的形式展现出来。

当我们用鼠标点击这个区域,在下方的性能报告和详情信息区域,就会呈现这一时间区间的性能情况:

图片图片

同时,还支持通过多种方式改变时间区间的长度:

  • 滚动鼠标滚轮;
  • 按住鼠标左键拖动;
  • 拖拽滑块时间区间两边的滑块;
  • 键盘上的 w 键和 s 键。

而使用键盘上的 a 键和 d 键则可以在固定时间区间长度的同时,精确修改时间区间的作用范围。

性能报告区

这个区域呈现了许多性能指标项,我们一起来看看吧。

Network

Network 部分展现的是网络请求的瀑布图,我们点击图片图标就可以展开这个面板:

图片图片

请求的文件类型

从图中可以看出,这些网络请求的瀑布图有许多种颜色,这些颜色就代表了请求对应的文件类型:

  • 图片蓝色: 请求 HTML 文档;
  • 图片紫色:请求 CSS 文件;
  • 图片黄色: 请求 JS 文件;
  • 图片绿色: 请求图片;

请求时长的构成

不知道小伙伴们有没有注意到,瀑布图中的每个请求都被分为了四个部分:左侧的线条、中间浅色的条形图形、中间深色的条形图以及右侧的线条;

这些划分又有什么含义呢?

  • 左侧的线:我们知道,在发送一个网络请求前,需要先解析 URL、建立连接等一系列操作;而左侧的线代表了 请求的开始,直到 Connection Start 事件组相关事件结束(包括 Connection Start 事件) ;
  • 中间的浅色部分条形图代表了 Request Sent 和 Waiting (TTFB,即 Time To First Byte) 的时间;TTFB 是指从发送请求到接收到第一个字节的时间,它表示了服务器响应的延迟时间。
  • 中间的深色部分条形图代表了从接收到第一个字节到请求的所有内容都被下载完成的时间。
  • 最后右侧的线代表了主线程等待的时间。

图片图片

请求的优先级

仔细观察每个请求,会发现请求左上角有个小小的方块,这个方块代表了本次请求的优先级。

深蓝色的方块表示本次请求优先级更高;而浅蓝色方块表示优先级较低。

图片图片

请求的详细信息

接下来,我们点击其中一个网络请求,可以看到下方的面板展示了请求的详情信息,包括请求时间、请求方法、优先级等等:

图片图片

Frames

Frames 区域展示了绘制一个帧所花费的确切时间;在这个部分,同样用颜色来区分了四种类型的帧:

  • 空闲帧(白色):表示在该帧中没有发生任何渲染或更新。
  • 正常帧(绿色图片):表示该帧在适当的时间内被渲染出来,没有出现延迟或问题。
  • 部分呈现帧(黄色,带有稀疏的宽虚线图案图片):表示 Chrome 尽力在适当的时间内渲染了部分视觉更新。例如:渲染器进程的主线程的工作延迟了,但合成器线程(如滚动)按时完成了渲染,则会出现这种情况。
  • 丢帧(红色,带有密集的实线图案图片):表示该帧由于性能问题或其他原因导致延迟,无法按时渲染。
  • Timings

    Timings 这个模块展示了衡量网页性能(FP、FCP、DCL、LCP、L)的几个关键指标,以及完成指标对应的时间:

    图片图片

    我们来看看这些指标都代表什么含义:

    FP (First Paint)

    指页面的首次渲染的时间点。在完成首次渲染之前,用户看到的都是 没有任何内容的白色页面,也就是我们常说的 白屏时间。

    FP 可以反映页面加载的整体速度。

    FCP (First Contentful Paint)

    指页面的首个内容绘制时间,即浏览器在页面上绘制出第一块有实际内容的区域(如文本、图像等)的时间点。

    FCP 反映了用户可以看到有意义的内容的时间。

    DCL (DOM Content Loaded)

    指当 HTML 文档被完全加载和解析后,DOM 树构建完成并且所有关联资源(如样式表、脚本等)已经下载完成,触发 DOMContentLoaded 事件的时间点。

    DCL 反映了页面的可交互性,表示页面已经准备好响应用户的操作。

    LCP (Largest Contentful Paint)

    指页面上最大的一个可见元素(如图片、文本等)绘制完成的时间点。

    LCP 是衡量页面加载速度的重要指标,它反映了页面主要内容的加载完成时间。

    L (Load)

    指页面完全加载完成的时间点。包括所有资源(如图片、样式表、脚本等)都已下载完成,并且相关的 DOM、CSSOM 和 JavaScript 都已经处理完成。

    L 反映了整个页面加载的时间。

    Layout Shifts

    这个指标用于衡量 页面加载过程中发生的视觉不稳定性。

    那么什么叫做视觉不稳定性呢?

    实际上,当用户在页面加载期间进行交互时,如果页面中的元素发生意外的移动或调整,会导致页面上的元素重新排列,从而造成视觉上的不连续和不稳定感。

    这种 元素的移动可能会干扰用户的操作,例如点击了一个不想点到的按钮,或者导致误触其他元素。

    我们点击 Layout Shifts 区域的色具体色块,在下方的 Summary 一栏就会展示此次位移的具体信息:

    图片图片

    Main

    这项指标可谓是整个性能报告中的重点区域,其中展示了 主线程在进行的相关活动。

    火焰图

    Main 指标中图表的这种展现方式称为火焰图;而堆叠组成火焰图的这些彩色矩形,则代表一个个函数调用堆栈:

    图片图片

    矩形颜色

    与 Network 用固定颜色来区分请求类型不同,Main 指标中的颜色是随机分配的。

    但是来自同一个脚本的调用在记录中会被分配为相同的颜色。

    长任务

    小伙伴们可能已经留意到了,在有的 Task 中除了灰色的区域外,还有部分被红色密集实线覆盖,同时右上角还有一个红色的三角 :

    图片图片

    这实际上是用来标识这个任务是个长任务。

    执行时长超过 50 毫秒的任务会被定义为长任务;而超过 50 毫秒的部分就会用这种红色密集实线覆盖图片

    这些长任务可能会阻塞主线程,导致页面卡顿、无法及时响应用户输入等等;是我们需要 重点关注 的对象。

    矩形堆叠逻辑

    图中位于最上方的 Task 表示 一个由浏览器调度和执行的任务单元;Task 的 长度就表示这个任务执行时间的跨度。

    而 Task 下方的这些矩形是根据函数之间的调用关系来堆放的,比如 ——

    上图中,一个指针事件 pointermove 的触发,导致了一个 (匿名函数调用(Function Call) ;而这个匿名函数调用又引起了 value 函数的调用...以此类推一直到最后的函数 n。

    任务具体信息

    下面我们来查看一下对应任务的具体信息。

    当我们选中任意一个任务时,下方的面板就会展现对应的信息:

    图片图片

    Summary

    Summary 选项卡展示了 当前任务的具体信息,包括长任务警告、总任务时长、各个子任务耗时等等:

    图片图片

    Bottom-Up

    Bottom-Up 选项卡将当前任务下所有活动都展示出来,并且根据时间进行倒序排序。

    这样一来,一眼就能看出是哪个活动耗费了较长的时间:

    图片图片

    并且还贴心的提供了筛选 (Filter) 功能和分组 (Grouping) 功能,方便我们分类查看:

    图片image.png

    图中可以看出,整个图表分为三列:

    • Self Time 表示这个根活动自身花费的时间;
    • Total Time 表示这个根活动自身以及导致的子活动花费的时间总和。
    • Activity 就是对应的活动名称;并且点击活动名称右侧的链接,还可以直接跳转到对应的源码。

    图片图片

    Call Tree

    Call Tree 选项卡可以用来查看当前任务下的根活动,以及根活动引发的一系列子活动的耗时。

    图片图片

    根活动是那些导致浏览器做一些工作的活动。比如前面提到的 pointermove ,浏览器会触发一个Event活动作为根活动,该事件可能导致处理程序执行,依此类推。

    可以简单理解为火焰图顶层的活动。

    Event Log

    最后的 Event Log 选项卡是按照活动在记录过程中发生的先后顺序来呈现表格的:

    图片图片

    这里的下拉不是用来做分组 (Grouping) 的,而是以时间为维度来过滤滤掉耗时少于 1 毫秒或 15 毫秒的活动:

    图片图片

    而旁边 Loading、Scripting、Rending、Painting 这些复选框,是用于通过类型来过滤表格中的数据:

    图片图片

    并且这里的表格多了一列 Start Time;顾名思义就是对应活动的开始时间。

    其余部分

    报告区中剩余的信息,比如 ——

    • GPU:展示了 GPU 的活动情况;
    • Compositor:展示了合成线程的活动情况;

    这些都大同小异,在这里就不一一展开讲啦,留给大家自己去探索。

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论