乐趣区

关于大前端:技术干货前端性能优化快速定位代码bug

分享人:Mark Wu( 吴银波 云智慧前端工程师,致力于云智慧大屏产品及 ITSM、DOMM、DOEM 等产品线定制化开发,领有丰盛的前端性能优化和开源我的项目教训。

背景介绍:

不晓得你有没有碰到过这些状况:

  • 被告诉下周一前肯定要解决某个 bug,当初曾经是周五下午了;
  • 上线封版前一天被告诉客户机器性能不行,打不开某个页面,过后曾经是早晨 10 点了;
  • 早晨 2 点接到电话,某个零碎当初运行不起来,然而今天要给客户领导演示,而后你还没带电脑回家 …

如果你也有这些状况,那么祝贺你,这只是开始 …

如果没有,那么也祝贺你,你迟早会遇到的 …

那么,如果咱们可能找到一些疾速定位问题的办法,那大概率能够防止这样的问题,大幅提高效率。

联合具体的示例来分享一下我是如何利用 Performance 性能面板和 console 面板来定位问题的,开端也和大家分享一个应用这个办法优化后造出的轮子。

一、Performance 性能剖析面板

当初看一下 Performance 性能剖析报告:

能够看到时间轴上面蕴含 FPS、CPU、网络等;这一块次要 关注 FPS,察看有没有飘红的区域,可定位到上面的 Main 指标对应的 js 执行过程,察看程序哪局部影响了页面性能,这能帮忙咱们疾速确定须要优化的代码地位;

还应关注总 阻塞工夫,这是对以后页面运行是否晦涩的一个总体评估,应尽可能减少阻塞工夫;

最初关注 摘要局部,比照正在执行脚本与渲染工夫,确定 JS 执行和页面渲染哪个为次要优化对象(优化往往是两者并行)。

上面两个示例别离偏重 JS 执行效率和页面渲染效率进行优化,JS 执行效率次要升高代码空间复杂度,缩小不必要的内存开销,防止深拷贝,及时革除定时器等;页面渲染效率次要缩小页面重排次数,尽量同步页面动画与显示器帧数刷新。

二、JS 执行性能优化示例

  1. 呈现问题

DOMM 定制化我的项目:现场某场景内 G6 拓扑组件节点数量一多,浏览器假死,开发环境无奈重现。

剖析:页面假死通常是 js 线程阻塞、栈内存溢出,或者是页面动画过于简单导致 css 线程卡死、频繁布局抖动等造成的。

Performance 剖析:

从上图能够看到 js 执行工夫比拟长,渲染工夫占用比拟短。这种状况先排除 css 线程以及布局抖动的影响,确定问题是在 JS 执行上。并且在页面性能优化时针对这种状况想要再去较大地优化页面渲染效率是很难也是不划算的,这个时候的重点也是在 JS 执行效率上。

  1. 应用 console 打印各环节工夫耗费,确定问题代码

通过对于 Performance 的 Main 进行剖析并联合代码剖析,确定问题代码区域,在代码执行次要节点上打印工夫耗费,针对耗时较大的区域代码进行细化,最终确定问题代码。

计算耗时打印

耗时打印状况:

剖析:能够看到这部分 JS 代码总执行时长 1027ms,其中计算节点、计算连线耗时最长,而且反复执行了两次,设置防抖函数。

剖析:设置防抖后,此段 JS 总执行时长 599ms,持续细化“计算连线”局部耗时打印。

细化耗时打印:

a、 连线计算 耗时过长

剖析:“计算连线”段 JS 代码被屡次援用,持续细化这部分耗时打印;

b、单次连线耗时

剖析:“连线耗时”为计算单次节点间连线耗时,大量执行且单次耗时不短,对此局部代码持续细化,发现存在可疑的代码 – 深拷贝。

c、深拷贝耗时

剖析:“克隆耗时”的打印法则和“连线耗时”相当,且存在耗时较长问题,应用累加计时打印深拷贝总体耗时。

剖析:深拷贝累加有三次打印,总耗时 679ms,占比很大。

耗时定位:每次深拷贝耗时较长,深拷贝算法须要优化或者连线计算逻辑避开深拷贝

剖析:拷贝层级过深,造成耗时较长,应用浅拷贝代替。

优化深拷贝耗时后打印

剖析:应用浅拷贝打印总耗时 6ms,绝对于原来的 679ms 耗时很短。

  1. 动画渲染剖析

当初不能确定现场部署就没有问题,再来看看拓扑节点数量对于 JS 执行以及页面渲染效率的影响。

i 加载 200 个节点前端渲染耗时

ii 加载 1 个节点前端渲染耗时

剖析:能够看到 200 节点与单节点页面渲染耗时相差不大,次要是执行 JS 脚本多了 25ms,因为现场最大会有 800 多个节点的状况,简略计算了下,发现耗时比照原先的 1027ms 仍有很大晋升。

三、动画渲染性能优化示例

遇到问题:之前开发一张大屏,本地跑没有问题,然而联调测试发现右侧的滚动组件模块(有 4 个)中有一个模块没有货色,接口失常返回,字段也是失常的。最初发现是接口返回了 190 多条数据,前端全副渲染了这些组件,以致模块假死。

先看下现场效果图。左侧别离是地图、轮播图、饼图、轮播图,两头下面是两个拓扑链路图轮播,上面是 4 个 echarts 图表,右侧是 4 个滚动模块(图片不全)。当初除了要解决上述问题还得做好整张大屏的加载同步。

现场大屏的展现成果↓

剖析:当初来看这个问题,既然全副加载会导致模块假死,那就不加载全副,而是采纳过一条渲染一条(onebyone)形式,当初演示单个成果:

onebyone 模式 单模块成果

注:绿框为可视区域,红框为滚动组件,渲染固定数量的滚动单位,利用 css 管制页面动画,定时刷新对应的滚动单位。

onebyone 模式 单模块 Performance 剖析面板

剖析:单组件运行已产生 JS 线程阻塞,执行 JS 脚本、渲染耗时相当。

onebyone 模式 4 模块 Performance 剖析面板

剖析:执行 JS 脚本、渲染耗时相当,产生较长 JS 线程阻塞,且页面会产生布局抖动、掉帧。

代码剖析:因为每次一个滚动单位过场后会被替换,引发重排,而后每个模块如此,4 个模块叠加,会始终间断引发页面重排,而后这里用的是 js 管制布局导致间距不统一。过后的改良计划是要缩小重排次数以及替换布局计划,怎么缩小重排次数?

“一次计算整个过局面板,每次过局面板过场后才去更新整个面板,替换为 flex 布局。”

当初来看一下这个计划的成果:

twomove 模式单模块状况

twomove 模式单模块 Performance 剖析面板

剖析:单组件运行未产生 JS 线程阻塞,单个模块同屏产生的 dom 数量比 onebyone 模式多,所以劣势并不显著。

twomove 模式 4 模块 Performance 剖析面板

剖析:执行 JS 脚本、渲染耗时相当,JS 线程阻塞工夫缩小,页面未呈现布局抖动、掉帧,多模块下劣势突出。

四、总结

通过 Performance 性能剖析确定次要优化方向,针对 JS 执行能够联合 Main 指标应用 console 对问题代码进行定位,针对页面渲染应缩小页面重排升高页面渲染耗费,重点优化阻塞工夫、页面掉帧问题。

持续对这个组件成绩进行优化,减少了 endWithNum 属性,管制一轮循环实现之后隔开的单位数量,并且修复了一些 bug,包含页面不可视后 raf 进行,css 持续运行造成的不同调问题,进行重复测试,确保稳定性,并新增了一些配置属性,做成了轮子 react-rollfree。

最初:轮子分享 react-rollfree

react-rollfree 实用于各种滚动组件场景,包含文本、图片、动画等,反对大数据量动静更新,根本可能笼罩各种滚动动画场景,前面会减少弹幕模式,扩大更多利用场景。

下载方式:npm install react-rollfree

源码地址:https://github.com/Markuuuu/r…

具体配置:

`` `* @animationDirection boolean -- 滚动方向,默认从下到上,从左到右 ` ``

`` `* @animationTime number -- 过场工夫 单位:S` ``

`` `* [@children](https://my.oschina.net/children117cl) [<jsx>] -- 滚动组件,反对隐式传入 ` ``

`` `* @childrenUpdateModel string -- 数据更新后更新列表,'now' 立刻更新,'later' 跑完更新 ` ``

`` `* @contextHeight number -- 单条轮播组件 height` ``

`` `* @contextWidth number -- 单条轮播组件 width` ``

`` `* @endWithNum number -- 结尾空置滚动单位数量 ` ``

`` `* @height number -- 滚动外框 height` ``

`` `* @horizontal boolean -- 横纵向轮播 `,默认横向 ``

`` `* @pauseWithHover boolean -- 默认开启,鼠标 hover 组件滚动进行 ` ``

`` `* @showBorder boolean -- 是否显示辅助设计边界 ` ``

`` `* @width number -- 滚动外框 width` ``

应用:

`` `<RollFree` ``

`` `animationTime={20}` ``

`` `contextWidth={2036}` ``

`` `contextHeight={2036}` ``

`` `horizontal={false}` ``

`` `width={2048}` ``

`` `height={1583}` ``

`` `>` ``

`` `{滚动 dom[]}` ``

`` `</RollFree>` ``

react-rollfree 默认成果

1000 个滚动模块效果图(实现黑客帝国特效)

写到最初:

更多智能运维方面资讯,请关注 云智慧 AIOps 社区

云智慧产品开源地址:

Github:https://github.com/CloudWise-OpenSource

Gitee:https://gitee.com/CloudWise

退出移动版