一个Chrome 运行时性能瓶颈分析案例

3,232 阅读6分钟

初诊

打开Chrome隐身模式

主要是为了确保有一个干净的测试环境, 不被其它因素所影响.

打开测试地址

谷歌性能测试地址 googlechrome.github.io/devtools-sa…

国内性能测试地址: gitee.com/hellojamesz…

可以看到如下画面:

可以看到页面蓝色小方块在运动

限制CPU速度

有些用户电脑的CPU性能很好, 可能无法较好的分析问题(难以发现低端配置设备的性能问题), 所以需要降速.

在Chrome浏览器控制台中找到"Performance" => "CPU"选项, 选择降低4/6倍性能

添加更好小方块, 找到性能瓶颈

上面已经限制了CPU的性能, 接下来需要寻找性能瓶颈了.

多次点击"Add 10", 向页面中添加小块, 直到感觉页面上小块运动时出现明显卡顿即可.

此时, 已经可以明显感觉到页面很卡顿了.

优化前后的效果对比

通过点击"Optimize"按钮, 可以提前感受下优化前后的效果对比

可以明显感受到优化前后页面的流畅度明显不一样.

了解Performance各模块

如何分析问题, 肯定是要依赖数据, 这里需要使用到Chrome的Performance功能.

将页面切换至非优化的状态, 点击"Record".

录制的结果如下图所示:

以上数据初学者可能看不明白, 没关系, 我们来一步步了解各部分的含义

FPS

fps, 指页面每秒帧数

  • fps = 60性能最佳
  • fps < 24会让用户感觉到卡顿, 因为人眼的识别主要是24帧

图中蓝色标记出的区域, 即FPS记录的信息 放大某一区域, 可以看到, FPS由两部分组成:

  • 红色的条
  • 绿色的半透明条

切换至优化状态

切换至已优化状态, 再进行录制后, 得到FPS数据如下:

可以看出:

  • 没有了红色条
  • 绿色半透明条的高度, 明显比没有优化时高不少

小结

  • 红色, 即帧数已经下降到影响用户体验的程度, Chrome已经标注出来, 这块有问题
  • 绿色, 即FPS指数, 所有绿色柱体高度越高, 性能越好

了解CPU

上图中FPS下的位置, 即CPU信息 我们采集些一个真实业务的CPU数据, 这里我抓取的是个人简书的performance, 如下图所示:

对比可以发现, CPU数据的一些特性:

  • CPU包括两种状态
    • 充满颜色
    • 不充满颜色
  • CPU是否充满颜色和FPS存在联系

了解NET

NET部分可以将屏幕逐帧录制下来, 能帮忙观察页面的状态, 分析首屏渲染速度

了解Frames

查看特定帧的FPS

Frames部分, 主要用于查看特定帧的FPS, 可以查看特定的帧情况, 悬停其上, 可以查看数据.

可以看到:

  • 这一帧的时间间隔是: 327ms
  • 当前FPS是1000ms/327ms = 3fps 这里主要体现的是页面两次刷新之间间隔了327ms

查看某个Frames块更详细的信息

点击某个Frames块, 可以查看到更加详细的数据

点击某个Frames块, 可以查看到更加详细的数据

  • Duration, 是当前帧从1.02s开始等待, 1.02s+326.97ms后进行了一次渲染
  • fps, 1000ms/326.97ms = 3fps
  • 最下面的是当前帧的视图画像

了解FPS快捷工具

在Chrome中, 还有一个More Tools选项, 选中"Rendering"选项

接着, 开启"FPS meter"选项

勾选后, 在页面上会出现一个FPS统计器, 如上图左上角.

暂时先不勾选"FPS meter", 不利于系统性学习

找到瓶颈

通过前面的内容, 我们已经知道页面有性能问题, 那接下来就要开始寻找原因了.

了解 Summary

对性能进行录制完成时, 会默认在底部显示一个 Summary摘要, 显示全局信息.

上面展示了0~4.90s录制时间的具体耗时:

  • script, 耗时1534ms
  • rendering, 耗时2557ms
  • Painting, 耗时281ms

主要了解这3个耗时, 但了解这3个耗时, 对于哪有问题, 还需要进一步的排查.

了解 Main

上图红色框出部分, 就是Main, 其中每一块是每一帧中所做的事情

目前仍看不出什么. 为了方便观看, 我们可在fps, cpu, net模块, 点击一下, 缩小时间区间:

如上图所示, 通过缩小时间区间, 来实现放大Main中的内容. 现在已经能够看到, Main中展示的"火焰图", 即函数调用的堆栈. 其中:

  • x轴表示时间
  • y轴表示调用函数, 函数中还包含依次调用的函数, y轴只占用x轴的一个时间维度

识别问题, 红色三角号

上图中, 可以看到Animation Frame Fired右上角有一个红色三角号, 这是Chrome自动帮助识别出有问题的部分, 就像FPS中的红色一样, 用来识别问题

上图可以到提示"Warning: Recurring handler took 318.21 ms", 即重复处理程序耗时318.21ms

追溯问题, 定位代码问题

点击Animation Frame Fired下面的"Function Call"

如上图, 可以看到函数调用代码中的位置, 可以点击进行查看:

虽然定位到了, 是方法 update造成的问题, 但不够明确, 所以需要进一步探索.

进一步分析问题位置

继续查看Main, 可以看到app.update下面有很多"紫色"的条, 紫色条本身表示渲染. 但请注意!!!的是紫色条上还有更小的, 运用前面学过的放大功能, 调整时间区间.

可以看到, 每个紫色条都有一个红色的小三角, 前面提到"红色三角是Chrome帮助自动识别有问题的地方", 查看提示信息: "Forced reflow is a likely performance bottleneck.", 即强制回流可能是性能瓶颈

点击查看摘要.

可以看到, 问题定位在了 performanceTest.html的第136行, 点击查看, 能够看到是对每一个元素进行样式修改.

这段代码的问题在于, 在每个动画帧中, 它会更改每个方块的样式, 然后查询页面上每个方块的位置. 由于样式发生了变化, 浏览器不知道每个方块的位置是否发生了变化, 因此必须重新布局方块以计算其位置.

避免这种情况的出现, 可以参考: 避免大型、复杂的布局和布局抖动

对比优化的效果

可以看到, 优化后的状态, script, render的时间都大大减少了, 因此fps明显提高.

性能优化知识储备

相关链接