愚墨的博客
  • 首页
  • 前端技术
  • 面试
只争朝夕不负韶华
  1. 首页
  2. 前端技术
  3. 正文

谈一谈性能优化那点事-上篇

2021年07月05日 4301点热度 0人点赞 0条评论

性能优化是每个公司每个开发人员都会做的事情。性能优化是指通过各种手段,提高应用程序的响应速度、吞吐量、资源利用率等性能指标,从而提高用户体验和系统效率。

性能优化是软件开发过程中非常重要的一环。需要注意的是,性能优化需要根据具体应用场景和需求进行,不能一概而论。同时,性能优化也需要进行平衡,不能只追求单一指标的提升,而忽略其他指标的影响。例如,为了提高响应速度,可能会牺牲系统的可靠性和安全性,因此需要进行综合考虑和权衡。

今天我们就简单谈一谈前端性能优化那点事。

我们要有一个共识。

首先,性能优化不能盲目,一定是问题导向的,一定是哪里有问题,我们才去优化哪里。

其次,性能优化要遵循二八原则,用20%的精力来解决80%的问题。

再次,性能优化要有数据支撑,否则无法反馈我们优化的成果。

最后,这个过程是可以持续重复的。

前端去做性能优化一般是从两个方面来做。 网络优化和渲染优化。

性能指标

而前端的性能指标每个公司可能不太一样,我司用的比较多的是FST(first-screen-time)首屏时间。首屏时间是衡量用户体验的一个重要指标。

这个指标的采集策略大概是这样的

Part1 首屏DOM时间:

  1. 使用 MutationObserver 监听 document 下的 DOM 变化 (添加或删除子孙节点)

  2. 在 callback 方法中,筛选并记录每次 mutation 时有效的新增节点 addedNodes 及其对应的时间点 performance.now(),

    push 到队列 mutationRecords 中,每个元素均为下面这种格式的一个对象 { nodes: addedNodes, startTime: startTime }

  3. 在 callback 方法中,还会判断是否要停止mutation 监听。目前有两个停止mutation 监听的场景:

    1. 通过该次 mutation 的 addedNodes 的 getBoundingClientRect 方法,与屏幕尺寸做对比,判断是否为首屏外的变更。

      当监测到超过 15 次首屏外变更时,停止监听

    2. 通过 setTimeout 设置定时器,3s 内没有再发生 mutation 时停止监听

  4. 停止监听后,开始对记录到的 mutationRecords 做处理。遍历 mutationRecords,筛选每一条记录的 nodes 中的有效首屏节点,

    并计算这些节点的权重和 score,push 到队列 validRecords 中,每个元素均为下面这种格式的一个对象 { score, startTime }

  5. 通过 validRecords 计算最后的 DOM 首屏时间。取队列中最后一个 score 大于阈值 3 的时间,若均小于3,则取 score 最大值的时间

Part2 首屏图片时间:

  1. 通过 performance.getEntriesByType('resource') 拿到图片资源的请求性能数据
  2. 计算首屏内图片最后加载完成的时间
  3. 比较首屏图片时间和首屏DOM时间,取更大的值作为最终的 FST 时间

技术方案细节

  1. 算法的起始时间点是如何获取的?

    在监听到 DOM 变化时,算法通过执行 performance.now() 获取到从页面开始加载到这次 DOM 变化所经历的时间。

    可以认为 performance.now() 的结果约为 Date.now() - performance.timing.navigationStart。

  2. MutationObserver 监听了什么内容?

    当设置了childList 和 subtree均为true时,将监听document节点下所有的添加节点和删除节点变化。

  3. start 方法执行前的mutation怎么收集?

    在预采集模块中同样创建了一个MutationObserver,负责收集预采集模块之后,start方法执行之前的mutation记录。

    start方法开始执行后,将关闭该MutationObserver,并率先处理之前收集到的mutation记录。

  4. 怎么筛选有效的mutation?怎么筛选mutation.addedNodes中的有效节点?

    通过mutation发生的目标的nodeName(mutation.target.nodeName),排除非视觉元素变更。另外排除没有添加节点(addedNodes)的mutation。

    通过addedNodes中每个节点的nodeName属性排除非视觉元素及iframe元素。另外还支持业务手动添加owl-ignore属性排除指定元素。

  5. 停止MutationObserver监听的条件是什么?

    1. MutationObserver上一次监听到DOM变化3s内没有再监听到新的DOM变化
    2. 检测到有效的首屏外节点超过15次。使用getBoundingClientRect方法拿到节点的位置信息,通过与屏幕尺寸做对比来判断是否在首屏内。

这个是大概的FST的获取逻辑,代码就不付了。收集到这些首屏时间,就需要进行一些分析。一般来说,我们会去p90或者p95的数值来做参考,目的是为了过滤掉一些极端用户场景。同时也会看1s内打开首屏的用户的占比。

流失率与首屏展现的时间的关系大家应该都明白,根据一些研究数据显示,如果页面的首屏展现时间超过3秒,那么用户的流失率就会显著增加。例如,如果页面的首屏展现时间为5秒,那么用户的流失率可能会达到30%以上。而如果页面的首屏展现时间能够控制在1-2秒之内,那么用户的流失率就会大大降低。

除了FST以外,还有很多时间指标

  • 首字节时间
  • DOM构建完成时间
  • DOM Ready 时间
  • 页面完全加载时间

这些都可以从Navigation Timing API接口中获取到。加上FST 这五个 指标足够我们分析了。

今天先写到这吧。。。。。。下一篇继续

标签: 暂无
最后更新:2023年07月23日

愚墨

保持饥渴的专注,追求最佳的品质

点赞
< 上一篇
下一篇 >

文章评论

取消回复

搜搜看看
历史遗迹
  • 2023年5月
  • 2022年9月
  • 2022年3月
  • 2022年2月
  • 2021年12月
  • 2021年8月
  • 2021年7月
  • 2021年5月
  • 2021年4月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年9月
  • 2020年7月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年1月
  • 2019年5月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年9月
  • 2018年3月
  • 2018年2月
  • 2018年1月
  • 2017年11月
  • 2017年7月
  • 2017年6月
  • 2017年3月
  • 2017年2月
  • 2017年1月
  • 2016年12月
  • 2016年11月
  • 2016年9月
  • 2016年8月
  • 2016年7月
  • 2016年6月
  • 2016年5月
  • 2016年4月
  • 2016年3月
  • 2016年2月
  • 2016年1月
  • 2015年12月
  • 2015年10月
  • 2015年9月
  • 2015年7月
  • 2015年6月
  • 2015年4月

COPYRIGHT © 2020 愚墨的博客. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS