前言
Hello 大家好! 我是前端 无名
背景
昨天在刷掘金的时候,看到零一01大神写的一篇文章 我优化了进度条,页面性能竟提高了70%,下面的评论许多人想了解chrome的调试技巧,自己反思了一下,经常看见大神性能调优,嗖嗖的打开chrome performance 面板,一顿猛如虎的操作,然后就能发现性能问题。作为小白的我, 看的是一脸懵逼,what? 昨晚赶紧抓紧时间看看chrome 开发者中心,我要成为大神!
案例
- 演示demo ,这里对比三种方案,来结合chrome performance 面板进行讲解。
本文demo代码基于 chrome Developers 修改,增加一种优化方案来进行对比。
部分代码片段
app.update = function (timestamp) {
for (var i = 0; i < app.count; i++) {
var m = movers[i];
if (app.scheme==1) {
//方案一
console.log("未优化的代码");
var pos = m.classList.contains('down') ?
m.offsetTop + distance : m.offsetTop - distance;
if (pos < 0) pos = 0;
if (pos > maxHeight) pos = maxHeight;
m.style.top = pos + 'px';
if (m.offsetTop === 0) {
m.classList.remove('up');
m.classList.add('down');
}
if (m.offsetTop === maxHeight) {
m.classList.remove('down');
m.classList.add('up');
}
}else if(app.scheme==2){
console.log("方案二优化后的代码");
var pos = parseInt(m.style.top.slice(0, m.style.top.indexOf('px')));
m.classList.contains('down') ? pos += distance : pos -= distance;
if (pos < 0) pos = 0;
if (pos > maxHeight) pos = maxHeight;
m.style.top = pos + 'px';
if (pos === 0) {
m.classList.remove('up');
m.classList.add('down');
}
if (pos === maxHeight) {
m.classList.remove('down');
m.classList.add('up');
}
}else if(app.scheme===3){
console.log("方案三优化后的代码");
var pos = parseInt(m.style.transform.slice(m.style.transform.indexOf('(')+1, m.style.transform.indexOf('px')));
m.classList.contains('down') ? pos += distance : pos -= distance;
if (pos < 0) pos = 0;
if (pos > maxHeight) pos = maxHeight;
// m.style.top = pos + 'px';
m.style.transform=`translateY(${pos}px)`;
if (pos === 0) {
m.classList.remove('up');
m.classList.add('down');
}
if (pos === maxHeight) {
m.classList.remove('down');
m.classList.add('up');
}
}
}
frame = window.requestAnimationFrame(app.update);
}
开始
我们结合Performance 面板来查找上述案例性能瓶颈。
- 为了保障我们的界面性能不受其他chrome 插件影响,我们以隐身模式打开谷歌浏览器,具体打开方法如下:
- Windows、Linux 或 Chrome 操作系统:按 Ctrl + Shift + n
- Mac:按 ⌘ + Shift + n
-
F12 打开DevTools 选择Performance
-
我们可以模拟移动CPU,选择x4 会比平常慢4倍。
记录运行时性能
针对演示demo ,方案一,我们可以很清楚的看到,页面上蓝色小方块增加到200的时候,fps已经从60降到了18左右,出现明显的卡顿效果,这个时候我们就需要在性能面板中进行录制,了解如何检测性能瓶颈。
- 在Performance面板中,点击Record(左上角小红圆点),开始录制。
-
稍微等上几秒钟。
-
点击stop。 devTool会停止记录,处理数据,过一会就会自动在性能面板显示结果。
到了这里看图表就比较懵逼了,这么多图形,该看那个呢,都是啥意思!
分析结果
获得页面性能后,我们怎么衡量页面的性能有没有问题呢?
FPS
衡量一个动画性能的重要指标就是FPS(每秒的帧数)。当动画以60FPS运行时,我们肉眼看上去动画是非常连贯的。
bad:
good:
当我们看到FPS上方显示红色条的时候,意味着我们的帧率特别低,用户体验特别不好。一般来说,绿色条越高,FPS越高。 所以我们分析性能图标第一眼看的就是FPS。
CPU
FPS下方会有CPU图表。 bad:
good:
在性能面板底部,图形图表的色彩越多,意味着CPU性能已经达到极限。当我们看到CPU长时间处于最大值状态,就需要考虑怎样去优化。
选取指定时间位置的屏幕截图
将鼠标悬停在FPS、CPU或者NET图表上,DevTools显示当前页面的屏幕截图,左右移动鼠标,可以范围范围选取。这对于手动分析动画性能很有用。
Frames
在Frames部分,将鼠标悬浮在绿色方块上,DevTools会显示特定的帧消耗时间。每帧可能远低于60FPS的目标。
上图中一帧耗费446.2ms,那么它的FPS为2。(1000ms/446) 大约是2FPS。远远低于60FPS的要求。
更直观的工具:FPS meter
-
按 Command+Shift+P (Mac) 或 Control+Shift+P(Windows、Linux)打开命令菜单。
-
输入show Rendering
3.在 Rendering 选项卡中勾选FPS meter
- 我们就能实时的看到FPS数据了。
寻找性能瓶颈
我们已经知道性能有问题了,但是具体问题是什么引起的呢?
-
我们首先要看Summary选项卡,我们可以看到蓝色部分占用了大部分,蓝色代表Rendering,该页面大部分时间用于渲染。那我们就需要尝试去减少渲染时间。
-
展开main 部分。这里展示的是随时间变化主线上的火焰图。X轴表示时间,Y轴表示事件。每一个条形代表一个事件,条形越长,消耗时间越长。当看到图形堆叠,表示同一时间处理事件较高。会导致性能问题。 bad:
good:
-
我们可以看到Animation Frame Fired 右上角有红色三角形。PS:红色三角表示可能存才与此事件相关问题的警告,注意:只要执行requestAnimationFrame() 就会有此回调。
-
单击Animation Frame Fired,底部Summary 栏会显示有关该事件信息,并附带链接。单击链接会跳转到源码相关行。
-
上图中能看出是调用app.update引起问题。
-
选择app.update事件,我们可以看到有一堆的紫色事件。看基本每个都有红色的三角形。随便选择一个,我们可以在Summary选项卡中看到更多信息。有一个forced reflows (强制回流)的警告。
我们点击链接进入源码可以看到:
原因找到了是由于:offsetTop导致发生回流。
ps:回流比重绘更加消耗性能,付出的代价更高。
问题原因
我们采用 offsetTop导致发生回流引起性能消耗。
上图可以看出,回流一定会导致重绘,重绘不一定导致回流。
哪些会引起回流呢?
- 改变dom元素的几何属性,常见的几何属性有 width、height、padding、margin、left、top、border 等等。
- 改变dom树的结构,主要指的是增加或减少dom节点,移动等操作。
- 获取一定特殊的属性值,如属性:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight 时,你就要注意了!除此之外:调用了 getComputedStyle 方法,也会触发回流。
优化
原来用anime.js 的时候,文档中有个介绍:
大多数CSS属性都会导致布局更改或重新绘制,并会导致动画不稳定。 因此尽可能优先考虑opacity和CSS transforms。
本文demo代码基于 chrome Developers 修改,代码中方案二是官方的优化方案:获取style.top值,去修改top值。
方案二:官方优化了一部分,去除offsetTop获取top值,但还是在修改top值,下面为官方的优化效果:
200节点的时候为38fps
方案三:修改top为修改transforms
优化后,我们可以看到200节点平稳的在60fps。
优化后preformance 图表效果
后语
现学现卖,我也要成为大神,欢迎大家多提意见。一赞一回!欢迎评论。