什么是火焰图?
火焰图是一种常用的性能分析工具。它展示了程序在时间轴上的执行情况,通过颜色深浅来表示消耗时间的长短。在 Web 开发中,火焰图通常被用来分析前端性能问题,例如卡顿、加载时间过长等等。它可以让我们更加清楚地了解程序中哪些方法消耗了时间,从而定位瓶颈并进行优化。
如何使用火焰图?
这里我们以Chrome浏览器为例,在 Chrome 浏览器中,要生成火焰图需要以下步骤:
- 打开一个网页并打开 DevTools(按
F12
或者右键菜单-检查) - 选择顶部菜单中的 Performance 选项卡
- 点击左上方的录制按钮开始记录性能数据
- 在网页中操作,模拟网页性能瓶颈
- 结束性能记录,停止按钮停止录制操作
- 通过 Summary 视图查看火焰图
现在我们来进行更详细的可视化讲解。右键检查打开控制面板,选择performance
面板选项:
1、Disable JavaScript samples:禁用JavaScript样例,忽略调用栈信息。
2、Enable advanced paint instrumentation (slow):开启加速渲染选项。
3、CPU:控制录制过程中,CPU的工作效率。
4、NetWork:控制录制过程中,网络加载速度。
5、Hardware concurrency:控制并发的。这个是根据浏览器版本来决定是否显示,所以有些人的浏览器里没有,有些人的浏览器里有这个选项。
如何读懂火焰图?
这里我们以React项目为例,使用create-react-app(简称cra)来快速创建项目,我们这里使用react@17版本为例,
index.js文件如下:
function App (){
return <div>这是函数式组件</div>
}
ReactDOM.render(
<App/>,
document.getElementById('root')
)
接下来录制的这个动作
以下面的动图为例:
这里我们主要分析的是“首页渲染”。我们进行的操作是先点击录制按钮
,然后再刷新页面
。这里可能会有小伙伴提问了,我们从刷新地址到页面渲染
这个过程中,也就花费了3-5s,但是录制时间为什么录制了10s?
这里就涉及了这个火焰图的基本原理
,这里先卖个关子,想知道答案的需要继续阅读哟~~
假设我们知道为啥要录制10s,我们来看一下这个录制的结果:
我们可以把这个结果看做是一张表格
,表格的标题是时间
,表格的每一行都代表着在时间基础上的不同维度,在这里面我们重点关注Timings
、Main
这2个维度就可以。
首先来看一下Timings
,在这个维度上我们看到浏览器为我们标注了5个标签,分别是LCP
、FP
、FCP
、DCL
、L
。
LCP
:最大内容的渲染。
FP
:首次渲染。
FCP
:首次有内容的渲染。
DCL
:HTML文件加载完成并且解析也完成。
L
:页面中所有资源都加载完成。
最后再关注一下Main
这个维度,在这个维度里,我们可以看到更多的代码细节,比如可以看到哪个代码块执行的时间较长,在某个时间段程序都干了啥等等。想要知道更多的有关这个维度的事情,请继续往下阅读。
火焰图的基本原理可以说下不?
火焰图的基本原理是将程序的执行时间沿着时间轴展开,并用彩色的“火焰”图形表示不同函数的执行时间
。图形中的每一个矩形代表一个函数,它的宽度表示这个函数执行的时间长度,颜色的深浅表示这个函数执行的时间长度所占比例,从而可以很清晰地看出程序中哪些部分占用了较多的时间。
这里来解释一下什么叫做将程序的执行时间沿着时间轴展开
?
首先,我们需要明确的是,所有的程序都有时间维度。就是当我们运行一个程序时,每一条指令都会在某个时刻执行,在另一个时刻结束。这个过程中,程序的运行时间是逐步推进的。
而火焰图所做的就是将这个运行时间沿着时间轴展开,类似于时间线,从程序开始执行到程序结束的时间范围内,每一时刻都显示程序中正在执行的部分代码的状态。
再具体来说,火焰图将时间轴分成了若干个时间片段,每个时间片段都代表了一个时间段内的执行状态。在每个时间片段内,程序的执行状态会用不同的颜色来表示,而每个颜色代表了一种特定的代码部分
。
通过观察这个图像,我们可以看出程序在不同时刻的执行状态,以及每种代码部分的相对运行时间和频率
。这样就能够清晰地看到代码的执行情况,看出哪些部分的代码运行时间较长,哪些部分的代码执行效率较差等信息。这有助于我们找出程序性能上的瓶颈,并作出优化或改进。
所以这就很好的解释了我们应该如何控制录制的时间
?还是以上面的例子来说,从地址栏刷新到页面渲染完毕
这个过程也就花3-5s的样子,但是我们却录制了10s,这是因为我们想要看到整个过程的全貌,所以我们只需要保证录制过程能够覆盖程序执行时间
就可以,不一定是10s,只要大于5s都可以。
如何用它阅读框架源码?
在这一个章节里,我们来看一下更多的有关Main
维度上的东西。在前面的部分我们知道Main
维度主要是暴露更多的代码细节,就冲它这一点,我们就可以用它来阅读React源码。我们以ReactDOM.render()
这个方法为例进行剖析:
这里有2种方法来看,一种是利用Main主线程
维度,另一种是 Timings
维度 + Main主线程
维度(2者综合起来看)。
第一种方法
,选中Main主线程
窗口,ctrl+f
打开搜索框,输入render
,这么做会查出来很多,所以需要你一个一个的确认。
这里还需要说明一点,在火焰图里,同一时刻上的代码阅读顺序一定是从上向下的
。
第二种方法
,我们同时打开Timings
与Main
这2个维度,Timings
里也会暴露出一些有用的信息
在这里它就暴露了这个信息:React Tree Reconciliation: Completed Root
。它在调和哎,我们知道React.render是会触发这个操作的
,同时打开Main主线程
,找到调和的这一个时间轴,我们就能看到render就在这个时间轴的左侧附近。当然,这种方法更偏向技巧性。
最后
好啦,本次分享到这里就结束啦,如果上面的分享有错误或者不足,欢迎大家指正,希望我写的对大家有启发。