lighthouse生成一个报告有些参数来源于performance,相对比lighthouse的分数和建议,performance用于记录和分析我们的应用在运行时的所有活动。它呈现的数据具有实时性、多维度的特点,可以帮助我们很好地定位性能问题。
Performance整体分析
1. Performance指标值
| 名词 | 解析 | 详细 |
|---|---|---|
| FP (First Paint) | 首次绘制 | 标记浏览器渲染任何在视觉上不同于导航前屏幕内容之内容的时间点 |
| FCP (First Contentful Paint) | 首次内容绘制 | 标记浏览器渲染来自 DOM 第一位内容的时间点,该内容可能是文本、图像、非空白canvas或SVG 甚至 元素. |
| LCP (Largest Contentful Paint) | 最大内容渲染 | 代表在viewport中最大的页面元素加载的时间. LCP的数据会通过PerformanceEntry对象记录, 每次出现更大的内容渲染, 则会产生一个新的PerformanceEntry对象. |
| DCL (Dom Content loaded) | 当 HTML文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,无需等待样式表、图像和子框架的完成加载 | |
| FMP(First Meaningful Paint) | 首次有效绘制 | |
| L (onLoad) | 加载完成 | 当依赖的资源, 全部加载完毕之后才会触发. |
| TTI (Time to Interactive) | 可交互时间 | 指标用于标记应用已进行视觉渲染并能可靠响应用户输入的时间点. |
| TBT (Total Blocking Time) | 页面阻塞总时长 | TBT汇总所有加载过程中阻塞用户操作的时长,在FCP和TTI之间任何long task中阻塞部分都会被汇总 |
| FID (First Input Delay) | 首次输入延迟 | 指标衡量的是从用户首次与您的网站进行交互(即当他们单击链接,点击按钮等)到浏览器实际能够访问之间的时间 |
| CLS (Cumulative Layout Shift) | 累积布局偏 | 总结起来就是一个元素初始时和其hidden之间的任何时间如果元素偏移了, 则会被计算进去。具体的计算方法可看这篇文章 《Cumulative Layout Shift (CLS)》 |
| SI (Speed Index) | 指标用于显示页面可见部分的显示速度, 单位是时间 |
2. RAIL 性能模型
| 名词 | 解析 | 详细 |
|---|---|---|
| response | 响应 | 用户输入之后是否能在100ms之内响应 这里的输入包括点击按钮、切换表单控件等,但不包括触摸滑动或滚动(50ms内完成较好) |
| animation | 动画 | 最近手机圈很流行将屏幕刷新率提升为90hz,这里hz就是帧率,90hz就是每秒有90帧,一帧就是一个画面。每秒看到的画面越多,我们就会感到越流畅,(每10ms内产生一帧较好) |
| idle | 浏览器空置状态 | 利用空闲的时间完成一些推迟的工作。推迟的工作应分为50ms的多个块进行。(尽可能增加空闲时间) |
| load | 加载 | 5s加载完成并且可以交互 |
3.Performancem面板参数
【第3以下配置都是用来模拟手机、慢网络下使用的】
| 名词 | 解析 |
|---|---|
| no recordings | 就是每一次的检测报告,可以根据每一次的检测报告,去进行性能优化的对比 |
| Screenshots | 是用来查看在每个时间段界面的变化 |
| Memory | 存储调用栈的大小,在不同时间段的不同大小; |
| Disable Javascript samples | 禁用 javascript 调用栈,关闭javaScript样本减少在手机运行时的开销,模拟手机运行时勾选 |
| Enable advanced paint instrumentation (slow) | 记录渲染事件的细节,选择frames中的一块,可以看到区域四多了个Layers |
| Network | 网络模拟,可以模拟在3G,4G等网络条件下运行页面; |
| CPU | 用来查看电脑的性能问题,主要为了模拟底CPU下运行性能 |
| HEAP | JavaScrip 执行的时间分布。 |
| 区域2:网页性能总览图(overview) |
| 名词 | 解析 |
|---|---|
| FPS | 每秒帧数,是用来分析动画的一个主要性能指标,对于动画而言标准是保持在60FPS。绿色越高越好,出现红色则表示FPS低(这就是你为啥觉得页面卡顿了),你可以在区域三Frames中看到具体的FPS值(见下面第二图) |
| CPU | 处理各个任务花费的时间,选择一段CPU统计可以在区域四的Summary看到统计表格 Scripting 脚本 Rendering 渲染 Painting 绘制 Loading 加载 ldle 闲置 |
| NET | 每条彩色横杠表示一种资源。横杠越长,检索资源所需的时间越长。 每个横杠的浅色部分表示等待时间(从请求资源到第一个字节下载完成的时间)。 |
| 区域3:线程面板 | |
| 名词 | 解析 |
| Frames | 帧线程,鼠标悬浮绿色块可以看到fps |
| Main | 主线程,负责执行Javascript, 解析HTML/CSS, 完成绘制。 可以看到主线程调用栈和耗时情况,每个长条都是一个事件,悬浮可以看到耗时和事件名 x轴指时间: 最上面的第一条就是事件触发的地方,直到结束,这条线是最长的 y轴指调用栈:上面的event调用了下面的子event,越到下面数量越少(瀑布) |
| Raster | Raster线程,负责完成某个layer或者某些块(tile)的绘制。光栅化线程池,用来让 GPU执行光栅化的任务 |
| Interactions | 用来记录用户交互操作,比如点击鼠标、输入文字、动画等 |
| Timings | 用来记录一些关键的时间节点在何时产生的数据信息,诸如 FP、FCP、LCP 等 |
| Compositor | 合成线程的执行记录,用来记录html绘制阶段 (Paint)结束后的图层合成操作 |
区域4:统计面板
| 名词 | 解析 |
|---|---|
| Summary | 统计图:展示各个事件阶段耗费的时间 |
| Bottom-Up | 排序:可以看到各个事件消耗时间排序 (1)self-time 指除去子事件这个事件本身消耗的时间 (2)total-time 这个事件从开始到结束消耗的时间(包含子事件) |
| Call Tree | 调用栈:Main选择一个事件,表示事件调用顺序列表(从最顶层到最底层,而不是只有当前事件) |
| Event Log | 事件日志 (1) 多了个start time,指事件在多少毫秒开始触发的 (2) 右边有事件描述信息 |
4.核心参数与视图解析
0.Network
资源网络请求的瀑布流。不同的颜色用于区分不同的资源类型(HTML、JS、Image等),鼠标悬浮可查看资源请求总耗时和优先级(Highest、High、medium、Low、Lowest)。鼠标点击某个资源请求可以在 Summary 选项卡中查看更详细的信息。
每个资源请求的图形中都存在一左侧线段、浅色矩形、深色矩形、右侧线段:
- 左侧线段:Request Sent 之前所有时间花费(Queueing ~ Proxy negotiation,后有详见👇🏻)。
- 浅色矩形:Request Sent + Waiting (TTFB)。从请求发出到浏览器接收到服务端响应的第一个字节花费的时间。
- 深色矩形:Content Download,内容下载耗时。
- 右侧线段:等待主线程的时间花费。
如果想更具体了解该网络请求的耗时分配,可以在 Network 瀑布图中查看该请求的具体时间序列:
-
Queueing:队列等待时间。以下情况下请求会进行排队:
- 存在更高优先级的请求;
- 同源仅能打开六个 TCP 连接的限制(仅适用于 HTTP/1.0 和 HTTP/1.1);
- 浏览器需要在磁盘缓存中短暂分配空间。
-
Stalled:请求停滞。请求可能因排队中所述的任何原因而停止。
-
DNS Lookup:DNS 查找。浏览器正在解析请求的 IP 地址。
-
Initial connection:初始连接。浏览器正在建立连接,包括 TCP 握手/重试和协商 SSL.
-
Proxy negotiation:代理协商。浏览器正在与 proxy server 协商请求。
-
Request sent:请求已发送。正在发送请求。
-
ServiceWorker Preparation: ServiceWorker 准备。浏览器正在启动 Service Worker。
-
Request to ServiceWorker: 请求 ServiceWorker。请求正在发送给 service worker.
-
Waiting (TTFB): 等待(TTFB,Time To First Byte)。浏览器正在等待响应返回的第一个字节,此时间包括 1 次往返延迟和服务器准备响应所用的时间。
-
Content Download:内容下载。浏览器直接从网络或 Service Worker 接收响应。Content Download 表示读取响应内容所花费的总时间。大于预期的值可能表示网络速度较慢,或者浏览器正忙于执行其他工作,从而延迟了响应的读取。
-
Receiving Push:接收推送。浏览器正在通过 HTTP/2 服务器推送接收此响应的数据。
-
Reading Push: 读取推送。浏览器正在读取之前接收到的本地数据。
1. 概览视图(Overview)
FPS(绿色曲线):帧率,60 为流畅,低于 30 会明显卡顿,红色表示帧率低。这是一个和动画性能密切相关的指标,它表示每一秒的帧数。图中绿色柱状越高表示帧率越高,体验就越流畅。若出现红色块,则代表长时间帧,很可能会出现卡顿。
CPU(彩色堆叠图):表示CPU的使用情况,不同的颜色片段代表着消耗CPU资源的不同事件类型。这部分的图像和下文详情面板中的Summary内容如 Scripting、Rendering)有对应关系,可以结合这两者挖掘性能瓶颈。
NET(灰色条):网络请求时间轴,粗略的展示了各请求的耗时与前后顺序,条的长度表示请求耗时,这个指标一般来说帮助不大。
2. 主线程火焰图(Main)
-
作用: 浏览器的主线程,负责执行 JavaScript、DOM 解析、样式计算、布局(Layout) 和 部分绘制(Paint)。
-
优化重点:
- 避免长任务(>50ms,会被红色角标标记),减少同步 DOM 操作。
-
X轴:时间线,可缩放查看细节。
-
Y轴:调用堆栈深度,上层调用下层。
-
颜色块含义:
黄色:JavaScript 执行(Scripting)。
紫色:布局计算(Layout)。
绿色:绘制(Painting)。
蓝色:HTML 解析、事件处理等。
-
关键指标:
长任务(Long Task):超过 50ms 的任务会阻塞主线程(标红)。
强制同步布局(Forced Synchronous Layout):紫色块中嵌套黄色块,表示 JS 触发了同步布局。
3. 摘要面板(Summary)
-
统计各阶段的耗时占比:
Loading:资源加载(HTML、CSS、JS)。
Scripting:JS 执行(包含编译、执行、事件回调)。
Rendering:样式计算、布局(Layout)。
Painting:绘制到屏幕(Paint、Composite)。
Other:其他时间(如浏览器内部处理)。
Idle:空闲时间。
4.Frames(帧)
作用:显示每一帧的渲染状态(如 FPS 和帧耗时)。
-
关键信息:
绿色:流畅帧(60 FPS,约 16.6ms/帧)。
红色:卡顿帧(<30 FPS,耗时 >33ms)。
-
优化重点:
确保动画和交互在 16ms 内完成。
查看每秒帧数。将鼠标悬停在其中一个绿色方块上会显示该帧的耗时和 FPS,如出现红色方块则表示出现掉帧。点选某帧可在 Summary 看到更多信息(触发该帧的相对时间和 CPU time)。
查看分层信息
-
开启图层信息:
- 控制面板开启
Enable advanced paint instrumentation。 - 在
Frames栏中选择某一帧。
- 控制面板开启
分层信息将在详情面板中的 Layers 选项卡中展示,可查看分层结果是否符合期望:
5.Animations(动画)
作用: 记录 CSS/JS 动画的执行细节(如 requestAnimationFrame 回调)。
-
关键活动:
蓝色:requestAnimationFrame 调用。
绿色:动画帧的绘制。
-
优化重点:
使用 transform/opacity 触发 GPU 加速,避免强制同步布局。
6. Compositor(合成器线程)
作用: 负责 图层(Layer)的合成(将绘制结果组合成最终屏幕图像)。
-
关键活动:
处理 transform、opacity 等 GPU 加速属性的变更。
-
优化重点:
优先使用合成器友好的属性(如 will-change: transform)。
7. Chrome_ChildThread(浏览器子线程)
作用: 浏览器的内部线程,处理 网络请求、扩展程序、插件 等任务。
-
典型场景:
粉色:网络请求(XHR/Fetch)。
灰色:扩展程序的后台逻辑。
-
优化重点:
检查第三方扩展是否阻塞主线程。
8. ThreadPoolServiceThread & ThreadPoolForegroundWorker(线程池线程)
作用: 浏览器的通用工作线程池,处理 文件读写、解码、加密 等异步任务。
-
典型场景:
图片解码、数据库操作、WASM 计算。
-
优化重点:
通常无需优化,除非发现特定任务耗时异常。
9. 其他视图
-
Interactions:用户交互事件(点击、滚动)的耗时。
-
Timings:关键时间点(如 DOMContentLoaded、First Paint)。
-
Memory:内存占用变化(需勾选 Memory 复选框)。
10.如何利用这些线程分析性能问题?
-
场景 1:动画卡顿
检查 Main 线程是否有长任务阻塞。
查看 Compositor 线程是否过载(如过多图层合成)。
确认 Animations 轨道中 requestAnimationFrame 是否按时触发。
-
场景 2:页面加载慢
观察 Chrome_ChildThread 中的网络请求是否延迟。
检查 Main 线程的 DOM 解析和 JavaScript 执行耗时。
-
场景 3:交互响应延迟
查看 Main 线程是否有同步布局(紫色 Layout 块)。
检查 ThreadPool 是否有密集任务(如解码大图)。
5.常见性能问题定位
1、卡顿(低 FPS):
检查 Main 线程中的长任务(红色块)。
优化 JS 执行(拆分任务、Web Workers)。
2、布局抖动(Layout Thrashing):
查找连续出现的 Layout 紫色块(强制同步布局)。
避免在循环中交替读写 DOM 样式。
3、渲染性能差:
减少复杂的样式计算(如 box-shadow 滥用)。
使用 will-change 或分层优化绘制(Composite)。
4、内存泄漏:
观察 Memory 面板是否持续增长。
检查未解绑的事件监听、游离的 DOM 引用。
6.优化技巧
-
代码拆分:用 requestIdleCallback 或 setTimeout 拆分长任务。
-
减少重排:批量修改 DOM,使用 DocumentFragment。
-
GPU 加速:对动画元素使用 transform 和 opacity。
-
节流高频事件:如 scroll、resize 使用防抖/节流。
7.基础面板介绍
区域1面板介绍
- 折叠
- 开启录制
- 刷新录制
- 清空性能分析文件
- 下载配置文件
- 保存配置文件
区域2面板介绍
- Screenshots(页面截图)
-
功能: 在录制性能数据时,自动捕获页面在不同时间点的视觉状态,生成时间线中的缩略图。
-
截图间隔通常为 100ms,按时间轴顺序排列。
-
显示页面渲染过程中的视觉变化(如布局偏移、动画效果)。
-
-
用途:
定位渲染问题:结合时间轴,观察卡顿或布局抖动时的页面状态。
- 例如,发现某个长任务(Long Task)执行时页面冻结,截图可直观显示当时的渲染状态。
-
分析加载过程:查看首次绘制(First Paint)、内容逐步加载的过程。
-
调试动画性能:检查动画是否流畅,是否存在掉帧。
操作建议:
- 在分析视觉相关的性能问题(如布局抖动、FPS 下降)时,务必勾选此选项。
2. Memory(内存分析)
-
功能: 在性能录制期间,记录内存使用情况的变化,包括:
-
JS 堆内存(JS Heap):JavaScript 对象占用的内存。
-
文档数(Documents):当前页面中的 HTML 文档数量。
-
DOM 节点数(DOM Nodes):页面中的 DOM 元素数量。
-
事件监听器(Listeners):绑定的事件处理函数数量。
-
-
用途:
-
检测内存泄漏:若 JS 堆内存或 DOM 节点数持续增长且不回落,可能存在内存泄漏。
-
优化内存占用:识别高内存消耗的操作(如大数组处理、频繁创建对象)。
-
分析垃圾回收(GC):观察 GC 触发的频率及其对性能的影响(可能导致卡顿)。
-
操作建议:
-
结合 Memory 面板(更详细的内存分析工具)使用,定位具体泄漏点。
-
关注录制过程中内存的波动趋势,而非绝对数值。
3. 3rd Parties(第三方资源高亮)
-
功能: 标记所有来自第三方域名(非当前页面域名)的活动,包括:
-
第三方脚本的执行(如广告、分析工具)。
-
第三方资源的加载(如图片、字体、API 请求)。
-
-
用途:
-
识别外部资源影响:快速定位拖慢页面性能的第三方服务。
- 例如,某个广告脚本执行时间过长,阻塞主线程。
-
优化第三方资源加载:决定是否延迟加载(async/defer)或替换为更轻量的方案。
-
遵守性能预算:避免因过多第三方资源导致页面臃肿。
-
操作建议:
-
对于标记的第三方活动,检查其耗时和触发时机。
-
使用 Network 面板 进一步分析第三方资源的加载细节(如大小、优先级)。
实际应用场景示例:
场景 1:页面卡顿分析:
-
勾选 Screenshots 和 Memory。
-
录制页面操作(如滚动、点击按钮)。
-
在时间轴中发现黄色长任务块(Scripting)且 FPS 下降:
通过 Screenshots 观察卡顿时页面是否处于渲染关键阶段。
通过 Memory 检查 JS 堆内存是否异常增长。
使用 3rd Parties 确认是否有第三方脚本正在执行。
场景 2:内存泄漏排查
1、勾选 Memory。
2、重复执行某个操作(如打开/关闭弹窗)。
3、观察 JS 堆内存和 DOM 节点数是否持续增加:
-
若每次操作后内存未恢复,可能存在未释放的引用(如未解绑的事件监听器)。
-
结合 Call Tree 或 Bottom-Up 视图找到泄漏的代码位置。
场景 3:第三方脚本优化
1、勾选 3rd Parties。
2、录制页面加载过程。
3、发现某个第三方脚本(如 analytics.js)在关键渲染路径中执行:
-
使用 async 或 defer 延迟加载。
-
评估是否可替换为更轻量的实现(如精简版 SDK)。
区域2面板总结:
-
Screenshots:可视化页面渲染过程,辅助定位视觉相关的性能问题。
-
Memory:监控内存使用趋势,发现泄漏或高消耗操作。
-
3rd Parties:快速识别并优化第三方资源的影响。
区域3面板介绍
- Disable JavaScript Samples(禁用 JavaScript 采样)★ 慎用
-
功能: 默认情况下,Performance 面板会通过采样记录 JavaScript 函数的执行时间(例如每 1ms 采样一次)。启用此选项会停止对 JavaScript 函数的详细采样,仅记录函数调用的开始和结束时间。
-
用途:
-
减少录制数据量:适用于长时间录制,避免生成过大的性能文件。
-
降低性能开销:采样本身会轻微影响性能,禁用后录制更接近真实运行状态。
-
-
副作用:
- 火焰图(Flame Chart)精度下降:JavaScript 函数的耗时统计会变得粗略,难以定位细粒度性能问题。
-
适用场景:
- 当你只需要分析宏观任务(如长任务、布局、绘制)而非具体函数耗时。
- Enable Advanced Paint Instrumentation (Slow)(启用高级绘制检测,慢速)★ 慎用
-
功能: 启用后,会详细记录每一帧的绘制(Paint)操作,包括:
-
哪些元素被重绘(Repaint)。
-
绘制区域的精确位置和大小(通过 Layers 面板 可查看)。
-
绘制耗时和触发原因。
-
-
用途:
-
诊断复杂的绘制性能问题:例如高频重绘、不必要的绘制区域(如整个页面重绘而非局部)。
-
优化 CSS 和动画:发现导致 paint 时间过长的样式属性(如 box-shadow、border-radius)。
-
-
副作用:
-
显著增加录制开销:可能导致页面变卡,录制文件变大。
-
仅适用于短期录制(如分析单次动画或交互)。
-
-
适用场景:
- 当 FPS 低下且 Painting 阶段耗时过高时,需定位具体绘制问题。
- Enable CSS Selector Stats (Slow)(启用 CSS 选择器统计,慢速)
-
功能: 记录所有 CSS 选择器的匹配耗时,统计哪些选择器在样式计算(Recalculate Style)中最耗时。
-
用途:
-
优化低效的 CSS 选择器:例如过于复杂的选择器(如 div:nth-child(3) > ul li a:hover)。
-
减少样式计算时间:发现频繁触发的选择器(如滚动时动态匹配的选择器)。
-
-
副作用:
-
增加样式计算的开销:可能影响录制结果的准确性。
-
数据量大:需结合 Bottom-Up 或 Call Tree 视图分析。
-
-
适用场景:
- 当 Rendering 阶段耗时过高,且怀疑是 CSS 选择器性能问题。
- Show Custom Tracks(显示自定义轨道)
-
功能: 显示开发者通过 Performance API 自定义的性能标记(如 performance.mark() 和 performance.measure())。
-
用途:
-
跟踪业务逻辑的耗时:例如记录关键用户操作的开始和结束时间。
-
与浏览器原生事件对比:将自定义标记与框架(如 React、Vue)的生命周期事件关联分析。
-
-
如何添加自定义标记:
// 在代码中插入标记
performance.mark('start_operation');
// 执行某些操作...
performance.mark('end_operation');
performance.measure('operation', 'start_operation', 'end_operation');
- 适用场景: 需要分析特定业务代码的性能,或与团队共享关键性能节点。
各选项的推荐使用场景:
实际案例分析
案例 1:动画卡顿
- 勾选 Advanced Paint Instrumentation。
- 录制动画过程,观察火焰图中高密度的绿色 Paint 块。
- 发现某个元素因
transform未触发 GPU 加速,导致频繁软件渲染。
案例 2:CSS 选择器性能问题
1.勾选 CSS Selector Stats。
2.录制页面滚动,在 Bottom-Up 视图中找到耗时的选择器(如 .list > li:first-child a.active)。
3.简化为类选择器(如 .active-link)。
案例 3:自定义业务逻辑分析
1.在代码中添加 performance.mark()。
2.勾选 Show Custom Tracks,录制后查看自定义标记的时间分布。
3.发现某个数据处理的 measure('data-processing') 耗时过长,需优化算法。
总结
-
优先默认配置:首次分析时无需启用所有选项,避免数据过载。
-
按需启用:根据怀疑的性能瓶颈(JS、CSS、Paint、业务逻辑)选择对应选项。
-
短期录制:高级选项会显著增加开销,建议录制时间控制在 10 秒内。
通过这些设置,可以更精准地定位性能问题,但需权衡分析深度与录制成本。
区域4面板介绍
1、Summary
-
功能:按阶段(如 Scripting、Rendering、Painting)统计耗时占比。
-
用途:快速定位耗时最多的阶段,判断性能瓶颈(如 JS 执行是否过长)。
2、Bottom-up
-
功能:按耗时从高到低列出所有活动(如函数、事件),显示每个活动的总耗时及其调用链。
-
用途:找到具体耗时的函数或操作(如某个事件处理函数)。
3、Call tree
-
功能:以树状结构展示调用关系,显示从顶层到底层函数的完整堆栈。
-
用途:分析函数调用层次,定位深层性能问题。
4、Event log
-
功能:按时间顺序列出所有事件(如点击、定时器、网络请求)。
-
用途:观察事件触发顺序及其耗时,排查事件处理逻辑问题。
区域5面板介绍
在 Chrome DevTools 的 Performance 面板 中,Insights 和 Annotations 是两个辅助分析性能问题的标签页,它们的功能和用途如下:
- Insights(性能洞察)
功能:
-
自动化诊断工具:Chrome 会自动分析录制数据,识别常见的性能问题。
-
提供优化建议:针对每个问题给出具体的修复方案(如拆分长任务、减少布局抖动等)。
-
基于规则检测:覆盖 Web 性能最佳实践(如 Core Web Vitals 相关指标)。
常见 Insight 类型:
界面特点
-
以列表形式展示,每条包含:
- 问题描述(含耗时和触发位置)。
- 代码定位(点击可跳转到源码)。
- 文档链接(详细解决方案)。
使用场景
- 快速发现已知性能问题,适合初步优化阶段。
2. Annotations(注释)
功能
- 自定义标记:开发者或框架(如 React、Vue)手动添加的性能标记。
- 时间轴高亮:在火焰图上显示彩色线条或区间,标注关键事件。
- 关联业务逻辑:将代码中的特定操作与性能数据关联。
操作建议
- 先看 Insights:快速定位共性问题。
- 再用 Annotations:结合自定义标记深入分析。
- 联用其他面板:结合 Main 火焰图和 Summary 验证问题。
8.Summary使用详细介绍
在 Chrome DevTools 的 Performance 面板 中,Summary(摘要) 是一个核心分析区域,展示点选活动或某时间段所有活动的各阶段时间耗时。
1、各指标含义及优化建议
2. 如何分析 Summary 数据?
步骤 1:定位耗时最高的阶段
-
如果 Scripting (黄色) 占比 >50% → 检查 JavaScript 代码(如长任务、频繁事件)。
-
如果 Rendering (紫色) 占比高 → 检查布局抖动或复杂样式计算。
-
如果 Painting (绿色) 占比高 → 检查绘制性能(如动画是否使用 GPU 加速)。
步骤 2:结合火焰图深入排查
- 点击 Summary 中的颜色块(如黄色 Scripting),会自动定位到 Main 线程火焰图 中对应的时间段,查看具体函数调用。
步骤 3:对比优化前后
-
修改代码后重新录制,观察 Summary 中各阶段占比变化。
- 例如:优化 CSS 选择器后,Rendering 时间减少。
总结
-
Summary 是性能优化的“风向标”,快速定位瓶颈阶段。
-
结合火焰图(Main、Rendering、Paint)深入分析具体问题。
-
优化优先级:通常按 Scripting > Rendering > Painting 顺序处理。
通过 Summary 面板,你可以高效判断性能问题的大方向,再针对性深入排查!
9.Bottom-up使用详细介绍
一、Bottom-Up 的核心作用
Bottom-Up 以耗时排序的方式,列出所有活动的详细耗时分布(如函数调用、事件处理、渲染操作),并显示它们的 调用链。他的作用可以解释了:
- “哪些函数/操作最耗时?”
- “耗时是如何被分配的(自身执行 vs 子调用)?”
二、面板指标详解
Bottom-Up 表格包含以下关键列:
**三、使用步骤与实战分析 **
步骤 1:按 Self Time 排序
-
点击 Self Time 列头,降序排列。
-
重点关注顶部条目:这些是性能瓶颈的直接原因。
步骤 2:展开调用链
-
点击行首的 箭头 ▶️ 展开调用层级,查看:
-
哪些父函数调用了该耗时操作。
-
子函数的耗时分布(定位深层问题)。
-
步骤 3:结合源码优化
-
双击 Activity 中的函数名 → 自动跳转到 Sources 面板 的对应代码。
-
检查是否有:
-
低效算法(如未优化的循环)。
-
重复计算(如未缓存的 DOM 查询)。
-
五、常见场景与优化案例
场景 1:高 Self Time 函数
- 现象:某函数的
Self Time极高,但子调用耗时少。 - 问题:函数自身逻辑复杂(如大数据处理)。
- 优化:
// 优化前(耗时操作集中在自身)
function processData() {
let result = 0;
for (let i = 0; i < 1e6; i++) { // 直接计算
result += Math.sqrt(i);
}
return result;
}
// 优化后(拆分任务)
function processChunk(start, end) {
let result = 0;
for (let i = start; i < end; i++) {
result += Math.sqrt(i);
}
return result;
}
场景 2:高 Total Time 调用链
-
现象:某函数的 Total Time 高,但 Self Time 低,子调用耗时长。
-
问题:深层嵌套调用(如第三方库或框架内部逻辑)。
-
优化:
-
减少调用次数(如缓存结果)。
-
替换轻量级实现。
-
场景 3:高频小耗时函数
-
现象:某函数的 Aggregated Self Time 高,但单次 Self Time 低。
-
问题:高频触发的小函数(如事件监听、动画回调)。
-
优化:
-
使用防抖/节流。
-
合并操作(如 requestAnimationFrame 批量更新)。
-
六、与其他视图的联动
-
Main 火焰图:
- 在 Bottom-Up 中点击条目 → 自动定位到火焰图中的对应位置。
-
Summary 面板:
- 对比
Scripting阶段的耗时是否与 Bottom-Up 中的函数一致。
- 对比
通过 Bottom-Up,你可以像显微镜一样深入代码的耗时细节,精准打击性能问题!
10.Call tree使用详细介绍
在 Chrome DevTools 的 Performance 面板 中,Call Tree(调用树) 是一种层级化的性能分析视图,用于展示函数调用的完整堆栈关系。它帮助你理解耗时操作的 调用路径,从而定位深层性能问题。以下是详细使用指南:
一、Call Tree 的核心作用
-
展示完整的调用链:从顶层入口(如事件触发)到底层耗时函数。
-
识别嵌套性能问题:发现隐藏在多层调用中的瓶颈。
-
与 Bottom-Up 互补:
-
Bottom-Up:从耗时最多的操作向上追溯。
-
Call Tree:从顶层调用向下展开,看整体流程。
-
二、Call Tree 面板详解
关键列说明
层级结构
- 顶层通常是 事件触发(如
Event: click)或 浏览器任务(如Animation Frame Fired)。 - 逐层展开(点击 ▶️ 箭头)可看到完整的调用栈。
三、使用步骤与实战技巧
步骤 1:定位高 Total Time 的顶层调用
- 展开 Main 线程下的顶级调用(如
Event: click)。 - 找到
Total Time最高的分支(可能是性能瓶颈的入口)。
步骤 2:逐层展开调用链
// 点击 ▶️ 箭头展开子调用,观察哪一层耗时突增。
Event: click (Total: 150ms)
└─ processData (Total: 120ms, Self: 30ms)
└─ calculate (Total: 90ms, Self: 90ms) ← 瓶颈在这里!
步骤 3:结合 Self Time 分析
-
如果某函数 Total Time 高但 Self Time 低 → 问题在子调用。
-
如果 Self Time 高 → 函数自身逻辑需要优化。
步骤 4:跳转到源码
- 双击函数名 → 自动跳转到 Sources 面板 的对应代码位置。
五、常见场景与优化案例
场景 1:深层次函数耗时
- Call Tree 表现:
Event: click (Total: 200ms)
└─ handleClick (Total: 180ms, Self: 10ms)
└─ renderList (Total: 170ms, Self: 20ms)
└─ updateDOM (Total: 150ms, Self: 150ms) ← 瓶颈
-
问题:
updateDOM自身耗时长(可能频繁操作 DOM)。 -
优化:
- 使用文档片段(
DocumentFragment)批量更新。 - 减少 DOM 操作次数。
- 使用文档片段(
场景 2:第三方库性能问题
- Call Tree 表现:
Animation Frame Fired (Total: 80ms)
└─ vueUpdate (Total: 75ms, Self: 5ms)
└─ lodash.merge (Total: 70ms, Self: 70ms) ← 第三方库耗时
-
问题:
lodash.merge在 Vue 更新中被频繁调用。 -
优化:
- 替换为轻量级合并逻辑(如
Object.assign)。 - 避免在动画循环中调用复杂库函数。
- 替换为轻量级合并逻辑(如
场景 3:高频事件监听
- Call Tree 表现
Event: mousemove (Total: 60ms, Self: 5ms)
└─ onMouseMove (Total: 55ms, Self: 55ms) ← 高频触发
-
问题:
onMouseMove处理函数未节流。 -
优化:
// 优化前
element.addEventListener('mousemove', onMouseMove);
// 优化后
element.addEventListener('mousemove', _.throttle(onMouseMove, 100));
通过 Call Tree,你可以像拆解洋葱一样层层分析性能问题,最终找到最内层的核心瓶颈!
11.Event log使用详细介绍
在 Chrome DevTools 的 Performance 面板 中,Event Log(事件日志) 是一个按时间顺序排列的详细活动记录,用于追踪页面运行期间发生的所有事件和任务。以下是它的完整使用指南和解析:
Start Time: 该活动的启动时间,它相对于录制的开始时间。Self Time:直接在该活动上花费的时间。Total Time:直接在该活动及其所有子活动上花费的时间。
一、Event Log 的核心作用
-
按时间轴顺序 显示所有活动(如点击、定时器、网络请求、渲染步骤等)。
-
精确到毫秒级 记录每个事件的开始/结束时间。
-
关联其他视图:点击日志条目可自动定位到火焰图中的对应位置。
二、Event Log 面板详解
关键列说明
常见事件类型
三、使用步骤与实战技巧
步骤 1:筛选关键事件
-
使用顶部的 Filter 输入框(如输入 click 或 Layout)。
-
勾选/取消勾选事件类型(如隐藏 Paint 专注逻辑问题)。
步骤 2:分析高 Duration 事件
-
点击 Duration 列头降序排列,找到耗时最长的事件。
-
示例:
Start Time: 520.3ms | Duration: 120.5ms | Event: click | Details: button#trigger表示点击事件处理耗时 120ms,可能存在长任务。
步骤 3:关联调用栈
-
点击事件条目 → 自动跳转到 Main 线程火焰图 的对应时间段。
-
展开调用栈查看具体函数(如 handleClick → processData)。
步骤 4:检查事件顺序
-
观察是否有 不合理的事件序列,例如:
-
在 requestAnimationFrame 中触发同步布局 → 导致帧率下降。
-
多个 setTimeout 密集执行 → 主线程阻塞。
-
四、常见场景与优化案例
场景 1:长任务诊断
-
Event Log 表现:
Event: click | Duration: 150ms | Details: button#loadData -
问题:点击事件处理耗时过长。
-
优化:
// 优化前(同步长任务)
button.addEventListener('click', () => {
processHugeData(); // 阻塞150ms
});
// 优化后(分片执行)
button.addEventListener('click', async () => {
await chunkedProcess(); // 分多次执行
});
场景 2:强制同步布局
- Event Log 表现:
Event: Function Call | Duration: 25ms | Details: updateGrid
Event: Layout | Duration: 8ms | Details: Forced reflow
-
问题:
updateGrid中触发了同步布局(如读取offsetHeight后立即修改样式)。 -
优化
// 优化前
function updateGrid() {
const width = element.offsetWidth; // 触发同步布局
element.style.width = width + 10 + 'px';
}
// 优化后(批量读写)
function updateGrid() {
requestAnimationFrame(() => {
const width = element.offsetWidth;
element.style.width = width + 10 + 'px';
});
}
场景 3:高频事件
- Event Log 表现:
Event: mousemove | Duration: 2ms | Details: window (重复数十次)
-
问题:未节流的
mousemove事件导致主线程过载。 -
优化:
// 优化前
window.addEventListener('mousemove', handleMove);
// 优化后(节流)
window.addEventListener('mousemove', _.throttle(handleMove, 100));
通过 Event Log,你可以像查看“手术记录”一样精确复盘页面运行的每一刻,快速定位异常事件!
12.Web Performance API
1. 高精度时间测量
performance.now()
- 作用:返回从页面加载开始到当前时刻的高精度时间戳(毫秒,精确到微秒)。
- 用途:测量代码执行时间,替代
Date.now()(精度更高)。 - 示例:
const start = performance.now();
doSomething();
const duration = performance.now() - start;
console.log(`耗时:${duration}ms`);
performance.timeOrigin
-
作用:返回页面加载的全局时间起点(Unix 时间戳,毫秒)。
-
用途:与其他时间系统(如 Date)对齐。
2.自定义标记与测量
performance.mark(name)
-
作用:在代码中创建一个自定义时间戳标记。
-
用途:标记关键代码节点(如函数开始/结束)。
-
示例:
performance.mark('start_work');
performance.measure(name, startMark, endMark)
-
作用:测量两个标记之间的时间间隔。
-
参数:
name:测量名称。startMark/endMark:标记名称或undefined(默认导航开始时)。
-
示例:
performance.measure('work_duration', 'start_work', 'end_work'); -
performance.clearMarks([name]) -
作用:清除指定的标记(不传参则清除所有)。
-
performance.clearMeasures([name]) -
作用:清除指定的测量(不传参则清除所有)。
长任务监控
PerformanceObserver
- 作用:监听特定类型的性能条目(如长任务、布局偏移等)。
- 用途:动态检测性能问题。
- 示例(监听长任务):
const observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => {
console.log('长任务耗时:', entry.duration);
});
});
observer.observe({ entryTypes: ['longtask'] });
关键性能指标(现代 API)
PerformancePaintTiming
-
作用:提供首次绘制(FP)和首次内容绘制(FCP)时间。
-
访问方式:
performance.getEntriesByType('paint');
PerformanceLayoutJank
- 作用:监控布局偏移(CLS 相关)。
PerformanceEventTiming
- 作用:记录交互事件(如点击、输入)的延迟。
内存监控
performance.memory(仅 Chrome 支持)
-
作用:返回 JavaScript 内存使用情况(如堆大小)。
-
示例:
console.log(performance.memory.usedJSHeapSize / 1024 / 1024, 'MB');
13.Performance 面板中
1. 关键时间节点(Navigation Timing)
2. 渲染关键指标(Rendering Metrics)
3. 交互相关指标(Interactivity)
4. 资源加载(Resource Timing)
5. 内存相关(Memory)
6.如何查看这些指标?
1、首次加载时间:
-
录制页面刷新 → 在 Summary 面板查看 Navigation Timing 阶段。
-
或通过 performance.getEntriesByType('navigation') 获取。
2、核心 Web 指标(LCP/FID/CLS):
- 使用 Lighthouse 面板直接检测。
3、资源耗时:
- 展开 Main 线程下的 Network 相关条目,或查看 NET 轨道。
优化优先级建议
- 首屏体验:优先优化 FP/FCP/LCP(视觉加载速度)。
- 交互响应:其次优化 TTI/TBT(减少输入延迟)。
- 稳定性:最后处理 CLS(避免布局跳动)。
14.查看分层
合成之前需要主线程先将页面分成若干层。为了确定哪些元素需要放置在哪一层,主线程需要遍历布局树来创建一棵层次树(Layer Tree),在DevTools中这一部分工作叫做 Update Layer Tree
也可以使用 will-change CSS 属性告诉浏览器对其单独分层。你甚至可以给页面上所有的元素一个单独的层,但分层并不是越多越好,当页面的层数超过一定数量后,分层的合成操作会比在每帧中光栅化页面的一小部分还要慢。DevTools Layers 面板中可查看网站如何被分层👇🏻。
CSS 复合图层(Composite Layer)是浏览器渲染优化中的关键机制,用于提升页面渲染性能。通常指的是浏览器如何处理和渲染页面上的不同元素,特别是涉及到性能优化和视觉效果的场景。
CSS中的一些属性和技术可以用来控制元素是否被单独渲染为一个图层,这有助于提高页面渲染性能和实现复杂的视觉效果。
触发复合图层创建的 CSS 属性
| 属性类型 | 示例 | 原理说明 |
| 3D Transform | transform: translateZ(0) | 强制开启 GPU 加速 |
| Opacity | opacity: 0.5 | 合成层独立处理透明度 |
| Will-Change | will-change: transform | 提前告知浏览器可能的变化,这样浏览器就可以为这些元素创建一个单独的图层 |
| Overflow 滚动 | overflow: scroll | 滚动容器自动分层 |
| Video/Canvas | 或元素 | 默认创建独立图层 |
| filter属性 | filter: blur(5px); | 滤镜效果 |