1.写在前面
前端性能调试是优化网页加载速度和运行效率的关键步骤,Chrome DevTools 的 Performance 面板 是核心工具;
2.Performance 面板使用步骤 ★ 基础
-
打开面板
在 Chrome 中按F12
→ 切换到 Performance 标签页。 -
开始录制
-
方式一:点击 ⚫️ 圆形按钮开始录制 → 操作页面 → 点击 🔴 停止。
-
方式二:勾选 Reload (刷新)按钮 → 自动录制页面刷新过程。
-
-
分析结果
录制结束后,面板会自动生成性能报告,分为多个视图区域。
3.核心参数与视图解析 ★ 基础
1. 概览视图(Overview)
-
FPS(绿色曲线):帧率,60 为流畅,低于 30 会明显卡顿,红色表示帧率低。这是一个和动画性能密切相关的指标,它表示每一秒的帧数。图中绿色柱状越高表示帧率越高,体验就越流畅。若出现红色块,则代表长时间帧,很可能会出现卡顿。
-
CPU(彩色堆叠图):表示CPU的使用情况,不同的颜色片段代表着消耗CPU资源的不同事件类型。这部分的图像和下文详情面板中的Summary内容如 Scripting、Rendering)有对应关系,可以结合这两者挖掘性能瓶颈。
-
NET(灰色条):网络请求时间轴,粗略的展示了各请求的耗时与前后顺序,条的长度表示请求耗时,这个指标一般来说帮助不大。
2. 主线程火焰图(Main) ★ 非常重要
-
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. 其他视图
-
Interactions:用户交互事件(点击、滚动)的耗时。
-
Timings:关键时间点(如
DOMContentLoaded
、First Paint
)。 -
Memory:内存占用变化(需勾选 Memory 复选框)。
4.常见性能问题定位 ★ 重要
-
卡顿(低 FPS)
-
检查 Main 线程中的长任务(红色块)。
-
优化 JS 执行(拆分任务、Web Workers)。
-
-
布局抖动(Layout Thrashing)
-
查找连续出现的 Layout 紫色块(强制同步布局)。
-
避免在循环中交替读写 DOM 样式。
-
-
渲染性能差
-
减少复杂的样式计算(如
box-shadow
滥用)。 -
使用
will-change
或分层优化绘制(Composite)。
-
-
内存泄漏
-
观察 Memory 面板是否持续增长。
-
检查未解绑的事件监听、游离的 DOM 引用。
-
5.优化技巧 ★ 重要
-
代码拆分:用
requestIdleCallback
或setTimeout
拆分长任务。 -
减少重排:批量修改 DOM,使用
DocumentFragment
。 -
GPU 加速:对动画元素使用
transform
和opacity
。 -
节流高频事件:如
scroll
、resize
使用防抖/节流。
6.基础面板介绍 ★ 基础
区域1面板介绍
- 折叠
- 开启录制
- 刷新录制
- 清空性能分析文件
- 下载配置文件
- 保存配置文件
区域2面板介绍
1. 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:内存泄漏排查
-
勾选 Memory。
-
重复执行某个操作(如打开/关闭弹窗)。
-
观察 JS 堆内存和 DOM 节点数是否持续增加:
-
若每次操作后内存未恢复,可能存在未释放的引用(如未解绑的事件监听器)。
-
结合 Call Tree 或 Bottom-Up 视图找到泄漏的代码位置。
-
场景 3:第三方脚本优化
-
勾选 3rd Parties。
-
录制页面加载过程。
-
发现某个第三方脚本(如
analytics.js
)在关键渲染路径中执行:-
使用
async
或defer
延迟加载。 -
评估是否可替换为更轻量的实现(如精简版 SDK)。
-
区域2面板总结
-
Screenshots:可视化页面渲染过程,辅助定位视觉相关的性能问题。
-
Memory:监控内存使用趋势,发现泄漏或高消耗操作。
-
3rd Parties:快速识别并优化第三方资源的影响。
区域3面板介绍
1. Disable JavaScript Samples(禁用 JavaScript 采样)★ 慎用
-
功能
默认情况下,Performance 面板会通过采样记录 JavaScript 函数的执行时间(例如每 1ms 采样一次)。启用此选项会停止对 JavaScript 函数的详细采样,仅记录函数调用的开始和结束时间。 -
用途
-
减少录制数据量:适用于长时间录制,避免生成过大的性能文件。
-
降低性能开销:采样本身会轻微影响性能,禁用后录制更接近真实运行状态。
-
-
副作用
-
火焰图(Flame Chart)精度下降:JavaScript 函数的耗时统计会变得粗略,难以定位细粒度性能问题。
-
-
适用场景
-
当你只需要分析宏观任务(如长任务、布局、绘制)而非具体函数耗时。
-
2. Enable Advanced Paint Instrumentation (Slow)(启用高级绘制检测,慢速)★ 慎用
-
功能
启用后,会详细记录每一帧的绘制(Paint)操作,包括:-
哪些元素被重绘(Repaint)。
-
绘制区域的精确位置和大小(通过 Layers 面板 可查看)。
-
绘制耗时和触发原因。
-
-
用途
-
诊断复杂的绘制性能问题:例如高频重绘、不必要的绘制区域(如整个页面重绘而非局部)。
-
优化 CSS 和动画:发现导致
paint
时间过长的样式属性(如box-shadow
、border-radius
)。
-
-
副作用
-
显著增加录制开销:可能导致页面变卡,录制文件变大。
-
仅适用于短期录制(如分析单次动画或交互)。
-
-
适用场景
-
当 FPS 低下且 Painting 阶段耗时过高时,需定位具体绘制问题。
-
3. Enable CSS Selector Stats (Slow)(启用 CSS 选择器统计,慢速)
-
功能
记录所有 CSS 选择器的匹配耗时,统计哪些选择器在样式计算(Recalculate Style)中最耗时。 -
用途
-
优化低效的 CSS 选择器:例如过于复杂的选择器(如
div:nth-child(3) > ul li a:hover
)。 -
减少样式计算时间:发现频繁触发的选择器(如滚动时动态匹配的选择器)。
-
-
副作用
-
增加样式计算的开销:可能影响录制结果的准确性。
-
数据量大:需结合 Bottom-Up 或 Call Tree 视图分析。
-
-
适用场景
-
当 Rendering 阶段耗时过高,且怀疑是 CSS 选择器性能问题。
-
4. 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');
-
适用场景
-
需要分析特定业务代码的性能,或与团队共享关键性能节点。
-
各选项的推荐使用场景
选项 | 适用场景 |
---|---|
Disable JavaScript Samples | 宏观分析任务阻塞(如长任务),减少录制开销。 |
Advanced Paint Instrumentation | 深入诊断绘制性能问题(如动画卡顿、不必要的重绘)。 |
CSS Selector Stats | 优化复杂 CSS 选择器导致的样式计算瓶颈。 |
Show Custom Tracks | 跟踪自定义业务逻辑或框架特定操作的性能。 |
实际案例分析
案例 1:动画卡顿
-
勾选 Advanced Paint Instrumentation。
-
录制动画过程,观察火焰图中高密度的绿色 Paint 块。
-
发现某个元素因
transform
未触发 GPU 加速,导致频繁软件渲染。
案例 2:CSS 选择器性能问题
-
勾选 CSS Selector Stats。
-
录制页面滚动,在 Bottom-Up 视图中找到耗时的选择器(如
.list > li:first-child a.active
)。 -
简化为类选择器(如
.active-link
)。
案例 3:自定义业务逻辑分析
-
在代码中添加
performance.mark()
。 -
勾选 Show Custom Tracks,录制后查看自定义标记的时间分布。
-
发现某个数据处理的
measure('data-processing')
耗时过长,需优化算法。
总结
-
优先默认配置:首次分析时无需启用所有选项,避免数据过载。
-
按需启用:根据怀疑的性能瓶颈(JS、CSS、Paint、业务逻辑)选择对应选项。
-
短期录制:高级选项会显著增加开销,建议录制时间控制在 10 秒内。
通过这些设置,可以更精准地定位性能问题,但需权衡分析深度与录制成本。
区域4面板介绍
-
Summary
-
功能:按阶段(如 Scripting、Rendering、Painting)统计耗时占比。
-
用途:快速定位耗时最多的阶段,判断性能瓶颈(如 JS 执行是否过长)。
-
-
Bottom-up
-
功能:按耗时从高到低列出所有活动(如函数、事件),显示每个活动的总耗时及其调用链。
-
用途:找到具体耗时的函数或操作(如某个事件处理函数)。
-
-
Call tree
-
功能:以树状结构展示调用关系,显示从顶层到底层函数的完整堆栈。
-
用途:分析函数调用层次,定位深层性能问题。
-
-
Event log
-
功能:按时间顺序列出所有事件(如点击、定时器、网络请求)。
-
用途:观察事件触发顺序及其耗时,排查事件处理逻辑问题。
-
区域5面板介绍
在 Chrome DevTools 的 Performance 面板 中,Insights 和 Annotations 是两个辅助分析性能问题的标签页,它们的功能和用途如下:
1. Insights(性能洞察)
功能
-
自动化诊断工具:Chrome 会自动分析录制数据,识别常见的性能问题。
-
提供优化建议:针对每个问题给出具体的修复方案(如拆分长任务、减少布局抖动等)。
-
基于规则检测:覆盖 Web 性能最佳实践(如 Core Web Vitals 相关指标)。
常见 Insight 类型
问题类型 | 说明 | 优化建议 |
---|---|---|
Long Tasks | 主线程阻塞超过 50ms 的任务(黄色长条)。 | 使用 |
Layout Shifts | 意外的布局偏移(CLS 问题)。 | 固定元素尺寸,避免动态插入内容。 |
Forced Synchronous Layouts | JavaScript 强制触发的同步布局(如循环中读写 | 批量 DOM 操作,缓存布局值。 |
Expensive Paints | 复杂的绘制操作(如大面积重绘)。 | 使用 |
界面特点
-
以列表形式展示,每条包含:
-
问题描述(含耗时和触发位置)。
-
代码定位(点击可跳转到源码)。
-
文档链接(详细解决方案)。
-
使用场景
-
快速发现已知性能问题,适合初步优化阶段。
2. Annotations(注释)
功能
-
自定义标记:开发者或框架(如 React、Vue)手动添加的性能标记。
-
时间轴高亮:在火焰图上显示彩色线条或区间,标注关键事件。
-
关联业务逻辑:将代码中的特定操作与性能数据关联。
常见 Annotation 类型
来源 | 示例 | 用途 |
---|---|---|
开发者手动添加 |
| 标记业务关键节点(如数据加载完成)。 |
框架自动生成 | React 的 | 分析框架生命周期耗时。 |
浏览器内置事件 |
| 关键页面生命周期事件。 |
界面特点
-
在时间轴上显示为:
-
竖线(瞬时事件,如
mark
)。 -
区间块(持续事件,如
measure
)。
-
-
点击可查看详细信息(如事件名、耗时)。
使用场景
-
深度调试时,关联性能数据与业务代码。
-
分析第三方库或框架的内部行为。
对比总结
特性 | Insights | Annotations |
---|---|---|
数据来源 | Chrome 自动分析生成。 | 开发者/框架手动添加。 |
内容类型 | 问题诊断 + 优化建议。 | 自定义事件标记。 |
交互性 | 提供修复方案和文档链接。 | 可点击跳转到代码上下文。 |
适用阶段 | 初步优化(快速发现问题)。 | 深度调试(关联具体逻辑)。 |
实战应用示例
场景 1:优化页面加载
-
录制页面加载性能。
-
Insights 提示:"Avoid enormous network payloads" → 发现未压缩的图片资源。
-
Annotations 显示
Vue.mounted
耗时较长 → 检查组件初始化逻辑。
场景 2:调试动画卡顿
-
录制动画交互。
-
Insights 提示:"Long animation frames detected" → 优化
requestAnimationFrame
逻辑。 -
Annotations 中定位到自定义标记
startAnimation
→ 确认卡顿发生在业务代码中。
操作建议
-
先看 Insights:快速定位共性问题。
-
再用 Annotations:结合自定义标记深入分析。
-
联用其他面板:结合 Main 火焰图和 Summary 验证问题。
7.Summary使用详细介绍
在 Chrome DevTools 的 Performance 面板 中,Summary(摘要) 是一个核心分析区域,它会将录制的性能数据按不同阶段分类统计耗时占比。
1. Summary 面板的位置
-
位于 Performance 录制结果的底部(默认展开)。
-
以饼图 + 表格形式展示各阶段的耗时比例。
2. 各指标含义及优化建议 ★ 重要
指标 | 颜色 | 含义 | 常见问题原因 | 优化建议 |
---|---|---|---|---|
Loading | 蓝色 | 资源加载时间(HTML、CSS、JS、图片等)。 | 网络慢、资源过大、未压缩。 | 压缩资源、HTTP/2、CDN、预加载。 |
Scripting | 黄色 | JavaScript 执行时间(包括解析、编译、执行、事件回调)。 | 长任务、频繁事件监听、未优化的算法。 | 拆分任务、Web Workers、防抖/节流。 |
Rendering | 紫色 | 渲染树计算和布局(样式计算、布局 Layout)。 | 强制同步布局、CSS 选择器复杂、频繁 DOM 操作。 | 避免同步布局、简化 CSS、批量 DOM 更新。 |
Painting | 绿色 | 像素绘制和合成(Paint、Composite)。 | 复杂样式(如阴影)、无 | 使用 |
Other | 灰色 | 其他浏览器内部操作(如扩展程序、垃圾回收)。 | 浏览器扩展干扰、内存泄漏。 | 禁用扩展、优化内存使用。 |
Idle | 白色 | 主线程空闲时间(未被占用的时间)。 | 无(空闲时间越多越好)。 | 无需优化,但可用来计算任务密度。 |
3. 如何分析 Summary 数据? ★ 重要
步骤 1:定位耗时最高的阶段
-
如果 Scripting (黄色) 占比 >50% → 检查 JavaScript 代码(如长任务、频繁事件)。
-
如果 Rendering (紫色) 占比高 → 检查布局抖动或复杂样式计算。
-
如果 Painting (绿色) 占比高 → 检查绘制性能(如动画是否使用 GPU 加速)。
步骤 2:结合火焰图深入排查
-
点击 Summary 中的颜色块(如黄色 Scripting),会自动定位到 Main 线程火焰图 中对应的时间段,查看具体函数调用。
步骤 3:对比优化前后
-
修改代码后重新录制,观察 Summary 中各阶段占比变化。
-
例如:优化 CSS 选择器后,Rendering 时间减少。
-
4. 其他注意事项
-
时间单位:所有时间均为毫秒(ms)。
-
颜色关联:Summary 颜色与火焰图中的颜色一致(如黄色=Scripting)。
-
多次录制:不同设备/网络下结果可能不同,建议取平均值。
总结
-
Summary 是性能优化的“风向标”,快速定位瓶颈阶段。
-
结合火焰图(Main、Rendering、Paint)深入分析具体问题。
-
优化优先级:通常按
Scripting > Rendering > Painting
顺序处理。
通过 Summary 面板,你可以高效判断性能问题的大方向,再针对性深入排查!
8. Bottom-up使用详细介绍
Bottom-Up 的核心作用
Bottom-Up 以耗时排序的方式,列出所有活动的详细耗时分布(如函数调用、事件处理、渲染操作),并显示它们的 调用链。他的作用可以解释了:
-
“哪些函数/操作最耗时?”
-
“耗时是如何被分配的(自身执行 vs 子调用)?”
二、面板指标详解 ★ 重要
Bottom-Up 表格包含以下关键列:
列名 | 含义 | 优化意义 |
---|---|---|
Self Time | 该活动 自身直接消耗的时间(不包括子调用)。 | 定位最耗时的原子操作。 |
Total Time | 该活动 总耗时(包含所有子调用)。 | 评估完整调用链的影响。 |
Activity | 活动名称(如函数名、事件类型、渲染阶段)。 | 识别具体代码或浏览器行为。 |
URL | 代码所在文件(仅限脚本)。 | 定位到源文件。 |
Aggregated Self Time | 同类活动的 累计自身耗时(如多次调用的同一函数)。 | 发现高频调用的性能热点。 |
三、使用步骤与实战分析
步骤 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 中的函数一致。
-
七、实际案例演示
录制结果分析
Activity | Self Time | Total Time | URL |
---|---|---|---|
| 120ms | 150ms | index.html |
| 80ms | 80ms | app.js |
| 5ms | 50ms | app.js |
-
结论:
-
(anonymous)
的 120ms 自身耗时 → 检查全局代码块。 -
processData
无子调用 → 直接优化算法。 -
requestAnimationFrame
总耗时高 → 检查动画逻辑。
-
八、注意事项
-
Self Time 与 Total Time 的关系:
-
如果
Self Time ≈ Total Time
→ 函数自身是瓶颈。 -
如果
Total Time ≫ Self Time
→ 子调用是瓶颈。
-
-
忽略极小值:关注占比 >5% 的条目。
通过 Bottom-Up,你可以像显微镜一样深入代码的耗时细节,精准打击性能问题!
9.Call tree使用详细介绍
在 Chrome DevTools 的 Performance 面板 中,Call Tree(调用树) 是一种层级化的性能分析视图,用于展示函数调用的完整堆栈关系。它帮助你理解耗时操作的 调用路径,从而定位深层性能问题。以下是详细使用指南:
一、Call Tree 的核心作用
-
展示完整的调用链:从顶层入口(如事件触发)到底层耗时函数。
-
识别嵌套性能问题:发现隐藏在多层调用中的瓶颈。
-
与 Bottom-Up 互补:
-
Bottom-Up:从耗时最多的操作向上追溯。
-
Call Tree:从顶层调用向下展开,看整体流程。
-
二、如何找到 Call Tree?
-
完成 Performance 录制。
-
在结果页面的底部标签栏切换到 Call Tree。
-
默认按 Total Time(总耗时) 降序排列。
三、Call Tree 面板详解
关键列说明
列名 | 含义 | 优化意义 |
---|---|---|
Total Time | 该函数及其所有子调用的总耗时。 | 评估整个调用链的影响。 |
Self Time | 函数自身代码的耗时(不包括子调用)。 | 定位函数内部的性能热点。 |
Function | 函数名或操作描述(如 | 识别具体代码或浏览器行为。 |
URL | 函数所在文件(如 | 跳转到源码调试。 |
层级结构
-
顶层通常是 事件触发(如
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));
六、与其他视图的联动
-
Main 火焰图:
-
在 Call Tree 中点击函数 → 火焰图自动定位到对应时间段。
-
-
Bottom-Up:
-
在 Call Tree 中找到可疑函数 → 切换到 Bottom-Up 查看其聚合耗时。
-
七、实际案例分析
录制结果示例
Function | Total Time | Self Time | URL |
---|---|---|---|
| 150ms | 0ms | - |
└─ | 140ms | 20ms | app.js |
└─ | 120ms | 120ms | utils.js |
-
结论:
-
calculate
是性能瓶颈(Self Time = Total Time
)。 -
优化方向:检查
utils.js
中的算法逻辑。
-
八、注意事项
-
忽略浏览器内部调用:如
(program)
或(garbage collection)
,除非占比极高。 -
关注业务代码:优先优化
Self Time
高的自定义函数。 -
多次录制对比:验证优化效果(如优化后
Total Time
是否下降)。
通过 Call Tree,你可以像拆解洋葱一样层层分析性能问题,最终找到最内层的核心瓶颈!
10.Event log使用详细介绍
在 Chrome DevTools 的 Performance 面板 中,Event Log(事件日志) 是一个按时间顺序排列的详细活动记录,用于追踪页面运行期间发生的所有事件和任务。以下是它的完整使用指南和解析:
一、Event Log 的核心作用
-
按时间轴顺序 显示所有活动(如点击、定时器、网络请求、渲染步骤等)。
-
精确到毫秒级 记录每个事件的开始/结束时间。
-
关联其他视图:点击日志条目可自动定位到火焰图中的对应位置。
二、Event Log 面板详解
关键列说明
列名 | 含义 | 示例值 |
---|---|---|
Start Time | 事件触发的起始时间(相对于录制开始)。 |
|
Duration | 事件持续的总时长。 |
|
Event Type | 事件类型(如点击、定时器、渲染阶段)。 |
|
Details | 事件的具体描述(如函数名、URL、元素标识)。 |
|
常见事件类型
事件类型 | 触发场景 | 颜色标识 |
---|---|---|
Function Call | JavaScript 函数执行(如事件处理函数)。 | 黄色 |
Timer Fired |
| 橙色 |
Event | 用户交互(如 | 蓝色 |
Parse HTML | 浏览器解析 HTML。 | 浅绿色 |
Layout | 布局计算(重排)。 | 紫色 |
Paint | 像素绘制到屏幕。 | 绿色 |
XHR | AJAX 请求(发送或完成)。 | 粉色 |
三、使用步骤与实战技巧
步骤 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));
五、与其他视图的联动
-
Main 火焰图:
-
点击 Event Log 中的条目 → 自动定位到火焰图的对应时间段。
-
-
Summary 面板:
-
对比
Scripting
阶段的耗时是否与 Event Log 中的高频事件匹配。
-
七、注意事项
-
时间精度:毫秒级记录,但浏览器可能有微小误差。
-
内部事件:如
(program)
或(garbage collection)
是浏览器内部行为,通常无需优化。 -
录制时长:长时间录制会导致日志过多,建议聚焦关键操作(如按钮点击后的 5 秒)。
通过 Event Log,你可以像查看“手术记录”一样精确复盘页面运行的每一刻,快速定位异常事件!
11.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])
-
作用:清除指定的测量(不传参则清除所有)。
3. 导航与页面加载计时
performance.timing
(已废弃,改用 Navigation Timing API
)
-
替代方案:使用
performance.getEntriesByType('navigation')
。 -
作用:提供页面加载各阶段的时间戳(如 DNS 查询、DOM 解析等)。
performance.navigation
(已废弃)
-
替代方案:通过
PerformanceNavigationTiming
接口获取。
4. 资源加载计时
performance.getEntries()
-
作用:返回所有性能条目(包括页面导航、资源加载、自定义标记等)。
-
用途:分析页面加载的所有资源耗时。
performance.getEntriesByType(type)
-
作用:按类型过滤性能条目(如
'mark'
、'measure'
、'resource'
)。 -
示例:
const resources = performance.getEntriesByType('resource'); resources.forEach(res => console.log(res.name, res.duration));
-
performance.getEntriesByName(name)
-
作用:按名称过滤性能条目(如自定义的
mark
或measure
)。
5. 长任务监控
PerformanceObserver
-
作用:监听特定类型的性能条目(如长任务、布局偏移等)。
-
用途:动态检测性能问题。
-
示例(监听长任务):
const observer = new PerformanceObserver(list => { list.getEntries().forEach(entry => { console.log('长任务耗时:', entry.duration); }); }); observer.observe({ entryTypes: ['longtask'] });
6. 关键性能指标(现代 API)
PerformancePaintTiming
-
作用:提供首次绘制(FP)和首次内容绘制(FCP)时间。
-
访问方式:
performance.getEntriesByType('paint');
PerformanceLayoutJank
-
作用:监控布局偏移(CLS 相关)。
PerformanceEventTiming
-
作用:记录交互事件(如点击、输入)的延迟。
7. 内存监控
performance.memory
(仅 Chrome 支持)
-
作用:返回 JavaScript 内存使用情况(如堆大小)。
-
示例:
console.log(performance.memory.usedJSHeapSize / 1024 / 1024, 'MB');
8. 其他工具 API
performance.toJSON()
-
作用:返回 Performance 对象的 JSON 表示(用于序列化)。
performance.setResourceTimingBufferSize(maxSize)
-
作用:设置资源计时缓冲区的最大条目数。
完整分类总结
API 分类 | 核心方法/属性 | 用途 |
---|---|---|
高精度计时 |
| 微秒级时间测量 |
自定义标记 |
| 标记和测量代码段 |
页面导航计时 |
| 分析页面加载阶段 |
资源加载计时 |
| 监控脚本、图片等资源加载 |
性能观察器 |
| 动态监听长任务、绘制等事件 |
关键 Web 指标 |
| 获取 FP/FCP、交互延迟 |
内存监控(非标准) |
| 检查 JS 内存占用(Chrome 专属) |
使用建议
-
基础分析:用
mark()
和measure()
标记关键业务逻辑。 -
高级监控:结合
PerformanceObserver
实时检测长任务或布局偏移。 -
生产环境:谨慎调用高频 API(如
performance.now()
),避免性能反噬。