如果我们要对网页做性能分析,也即是是当你的页面在浏览器运行时的性能表现,而不是下载页面的时候。我们常用的🔧就是Chrome DevToos Performance
本篇旨在给出使用Chrome DevToos Performance调优的一些基础知识,用Performance工具去分析一个现有的项目,怎么去分析,从而找到性能瓶颈
是不是感觉东西很多,我第一次看这个的时候很烦躁,这尼玛谁会看,太难了。后来坚持看,慢慢的发现一点不难。
我们平时用的多的就是图上的6个区域,具体含义:
圈1:我们仔细看图就会发现,在这一长条最右边有一个“FPS”,这就是FPS图,我们应该已经看过FPS相关的文章,它是页面每秒帧数,是衡量性能的指标,如果能保持60FPS的话,则证明不错,如果小于24就会出现卡动。放大FPS图你会看到:
圈2:这块区域同理,右边有标注“CPU”,包括两种状态:
cpu是否充满颜色和fps存在联系
其实在CPU的下面还有一个NET,这个主要是将屏幕逐帧录制下来,可以帮助观察页面的状态,主要用处,可以帮助分析首屏渲染速度
圈3:你☑️了Screenshots,每一时刻页面选择的快照
圈6:是一个综合面板,
圈5:是对圈一的一个详细面板,主要是看Frames,
查看特定帧的fps,Frames会fps的对应关系,如下图这就是一帕
鼠标悬停其上,可以查看数据,这一帕刷新需要的Duration、FPS和CPU time。这一帕的时间间隔,也就是页面两次刷新之间间隔了67.42ms,fps=1000/67.42 = 14.83fps,约等于14fps
圈6:如果你已经理解了其他4个面板,相信你也已经发现了一些有性能问题的页面了,但是你还不知道为什么会有性能问题吧?
对性能进行录制完成的时候,会默认在底部展示一个Summary摘要,显示全局的信息, 0 – 6.60 s录制时间的具体耗时:
主要就是这3个耗时,知道了这三部分耗时,只是知道了,哪有问题,但具体问题在哪呢?
你可以去看圈5中的Main:
红色边框圈出来的,就是Main部分,其中每一块是每一帧中所做的事情,目前这样看不出来什么,脑壳疼,为了方便我们观看,我们可以在fps、cpu、net模块,点击一下,或者滑动鼠标,缩小时间区间
注意看上图红色框标记的区域,基本是一个帕的信息了,现在已经能够看到,Main中展示的是火焰图,也就是函数调用的堆栈
火焰图,可以简单理解,x轴表示时间,y轴表示调用的函数,函数中还包含依次调用的函数,y轴只占用x轴的一个时间维度
同样可以看到“红色三角号”,这就是chrome自动帮助识别出有问题的部分,还记得FPS也有“红色三角号”吗?
我们点击带“红色三角号”,再看底部的“Summary”的汇总:
注意:Wwring:Recurring handler took 86.08 ms(重复处理程序耗时86.08毫秒)
我们可以点击底部的代码路径跳转:
目前还看不出问题,所以我们还需要继续按照函数调用栈找问题,直到找到我们业务代码块,才有可能定位问题
我们也可以根据选中某一个fps低的帕,去看Summary
既然汇总说这一帕总共共耗时100ms,其中:
Summary右边还有几个tab栏,
我一般喜欢看Event Log面板,其实它和Main差不多的意思,我们可以只看耗时较长的事件,然后看里面的调用栈:
就这样,一层一层往下看直到找到存在性能问题的代码块
react 项目在地址栏后加上?react_perf 后事件会被归类到 user Timing 中 React 文档,就是图中的 Timings
图中 1 区域表示每一帧,一格代表一帧,区域 2 表示 react 组件更新,可以看出更新的组件以及花费的时间,区域 3 就是主进程,结合一帧可以看出 react 组件已经更新了多次,但是页面渲染只执行了一次,查阅文档后发现 js 引擎线程与 GUI 渲染线程是互斥的,只有 js 引擎线程空闲时才会调用 GUI 渲染线程,这里可能是一个优化点
椭圆标记的区域是四个可以切换的 tab:
Self Time和Total Time以及Activity,其中的Self Time代表函数本身执行消耗时间,Total Time则是函数本身消耗再加上在调用它的函数中消耗的总时间
事件 | 描述 |
---|---|
Parse HTML | 浏览器执行 HTML 解析 |
Finish Loading | 网络请求完毕事件 |
Receive Data | 请求的响应数据到达事件,如果响应数据很大(拆包),可能会多次触发该事件 |
Receive Response | 响应头报文到达时触发 |
Send Request | 发送网络请求时触发 |
事件 | 描述 |
---|---|
Animation Frame Fired | 一个定义好的动画帧发生并开始回调处理时触发 |
Cancel Animation Frame | 取消一个动画帧时触发 |
GC Event | 垃圾回收时触发 |
DOMContentLoaded | 当页面中的 DOM 内容加载并解析完毕时触发 |
Evaluate Script | A script was evaluated. |
Event | js 事件 |
Function Call | 只有当浏览器进入到 js 引擎中时触发 |
Install Timer | 创建计时器(调用 setTimeout()和 setInterval())时触发 |
Request Animation Frame | A requestAnimationFrame() call scheduled a new frame |
Remove Timer | 当清除一个计时器时触发 |
Time | 调用 console.time()触发 |
Time End | 调用 console.timeEnd()触发 |
Timer Fired | 定时器激活回调后触发 |
XHR Ready State Change | 当一个异步请求为就绪状态后触发 |
XHR Load | 当一个异步请求完成加载后触发 |
事件 | 描述 |
---|---|
Invalidate layout | 当 DOM 更改导致页面布局失效时触发 |
Layout | 页面布局计算执行时触发 |
Recalculate style | Chrome 重新计算元素样式时触发 |
Scroll | 内嵌的视窗滚动时触发 |
事件 | 描述 |
---|---|
Composite Layers | Chrome 的渲染引擎完成图片层合并时触发 |
Image Decode | 一个图片资源完成解码后触发 |
Image Resize | 一个图片被修改尺寸后触发 |
Paint | 合并后的层被绘制到对应显示区域后触发 |
选中红点的框之后可在详情区查看信息,此时浏览器已经给出了性能瓶颈的警告, 'Idle callback execution extended beyond deadline by 19.72 ms',点击 utils.js 文件可以看到具体是哪个方法,这里可能是一个可以优化的地方,如图