性能优化进阶 💥 前端性能埋点&监控体系建设!

388 阅读10分钟

前言

页面性能对于任何平台而言都至关重要,糟糕的性能会导致用户流失和口碑下降等。根据 Google 在 2017 年发表的文章表示,超过 53% 的用户在页面加载时间超过 3 秒时就会离开,而当加载时间达到 5 秒时,用户离开的概率增加了 90%。随着近些年网络的快速发展,用户对于页面加载缓慢的容忍度相信就更低了。用户反馈问题然后进行解决固然是一种解决途径,但单靠用户遇到问题来反馈是不现实的,因此,我们需要建立前端性能数据采集和监控体系,通过数据来驱动性能优化。目前,性能监控主要有两种方式:第一种是合成监控(SYN) ,通过 Lighthouse、Dareboost 等提供的能力,在一个模拟的场景里去运行页面,然后得到性能指标和性能报告,以反映页面的性能情况;第二种是真实用户监控(RUM) ,用户在页面上访问时采集真实的性能数据并进行上报,然后对采集到的性能数据进行定量分析和监控。合成监控这种方案应用较为简单且技术较为成熟,但是模拟场景终究较为单一,数据也不稳定,用户在使用过程中遇到的场景远比单次模拟执行更加复杂,并且当系统处于快速迭代阶段的话单次模拟得到的数据只针对当前版本而言,相比之下,真实用户监控更加能够反应用户的真实情况,因此我们选择采用真实用户监控的方案 🏆。

Step1:性能指标确认

第一步我们需要做的就是确认性能指标,当我们在说一个页面很快或很慢的时候,快慢只是一个主观感受,我们需要具体的数据来进行衡量页面访问的快慢情况,那么如何定义合适的性能指标呢?目前,业界关于前端页面性能指标的定义已经有非常多的内容,例如:

  • Lighthouse 10 对网站的性能评分主要基于 First Contentful Paint、Speed Index、Largest Contentful Paint、Total Blocking Time 和 Cumulative Layout Shift 等 5 个维度加权计算生成;
  • web.dev 中还介绍了 First Input Delay、Interaction to Next Paint、Time to First Byte 等以用户为中心的性能指标,还可以通过 PerformanceObserver 等 Web API 自定义性能指标;

对于研发人员而言,业界所给出的这些性能指标固然是我们所需要关注的内容,然而,对于普通用户而言,他们并不关心平台这些性能指标的具体表现如何,他们的直观感受是我访问的页面是否快速展现内容?我进行的操作是否快速给出反应?目前业界所给出的性能指标并没有能够直接反应用户这些主观感受的,或者说需要结合多个指标来进行衡量,并且页面的性能情况不仅仅是前端渲染还有后端接口等因素综合而成的。基于这个情况,我们使用 “关键交互耗时”“用户体感耗时(FMP)” 这两个性能指标用于衡量页面的性能情况,以更加贴近用户视角的真实感受。

指标名指标概念指标说明计算公式
用户体感耗时用户进入页面展示关键内容耗时用户刷新进入页面到核心接口返回并且页面渲染完毕;SPA 页面首次进入指定 tab 到 tab 核心接口返回并且页面渲染完毕;time = 页面核心内容渲染完成时刻 - 进入路由时刻
关键交互耗时用户交互操作的响应耗时用户通过页面可交互区域触发某个行为场景到该场景结束(查询类:伴随接口调用结束;非查询类:纯 JS 逻辑计算)time = 交互自定义结束时间 - 交互自定义开始时间

Step2:性能指标埋点

目前,前端常见的埋点方案主要有 3 种:代码埋点、可视化埋点和无痕埋点。可视化埋点和无痕埋点较难进行自定义,根据上述“关键交互耗时”和“用户体感耗时”这两个性能指标的说明,性能数据的统计口径较为依赖于我们人为来确定核心内容或所期望内容展示的时间点,因此我们采用手动编码的方式进行代码埋点 🏆(未来可考虑通过设定特定的规则来自动确认核心内容,例如占据页面空间、元素到根节点的长度等)。具体埋点方式可参考 👉 定义更贴近“用户的性能指标,手把手教你前端埋点! - 掘金”

Step3:监控性能数据

性能埋点数据的上报这只是迈出了第一步,真正关键的是如何利用好这些性能埋点数据,建立性能监控体系,实现良性循环并可持续。通过不断地改进和完善性能监控体系,基于数据驱动性能优化,提升系统的性能表现,提高用户体验,同时实现系统的持续稳定运行。

Untitled.png

在性能优化专项治理阶段,监控指标的视角更加聚焦于点,关注于核心页面具体的性能指标,有针对性地进行性能数据监控和优化;而未来当性能优化进入到深水区或者整体趋于良好后,完善全平台页面的性能数据上报,监控指标的视角可以由点及面,将视角转为全局整体的性能情况,例如整体性能达标率、整体页面性能情况、整体耗时占比分布等。在性能优化专项治理阶段,我们根据页面 PV 情况或者业务意义等多角度综合考虑对页面进行优先级划分,重点关注系统核心页面的性能数据,即各核心页面的用户体感耗时和页面中的关键交互耗时,并从两个角度监控性能指标的情况:

  1. 关注趋势波动:选择性能指标的 P90 分位值 + P95 分位值 + P99 分位值结合样本量来分析性能情况并通过环比数值关注波动情况。对性能的要求越高,关注视角就需要使用越大的分位值,例如承诺 99% 的用户体感耗时都小于 3s,那我们就关注 P99 分位值,但如果当前人力紧张,那我们可以承诺 95% 或 90%,甚至 50% 的用户来满足相应目标,分阶段进行性能优化;同时,保证分位值的稳定也能够体现系统的稳定性。
  2. 关注尾部场景:选择 BadCase 数量 + 占比 + 影响用户数等来分析尾部场景并关注极端情况。尾部场景最直接体现就是最大值,但由于数据上报存在一定的脏数据,直接看最大值会有较多异常情况,例如用户网络异常、用户页面卡顿、时机上报异常、微任务堆积、用户特殊操作路径等,因此以 P99 数值作为参考来定义 BadCase,使用前一季度 P99 数值作为基准,超过该基准值的视为 BadCase。

基于所确定的监控指标,搭建监控体系的形式主要分为两个方面:

  1. 图表看板搭建 + 看波动:对所有核心页面的用户体感耗时和关键交互耗时进行看板搭建,直观展示了指标的 P99/P95/P90 分位数值的波动情况,以反应页面的性能情况,此外还搭建了 BadCase 以季度为周期进行统计的数量/占比/影响用户数看板,直观展示尾部场景情况。
  2. 消息推送配置 + 周解读:以周为统计周期进行群消息周报推送,包括对所有核心页面的用户体感耗时和关键交互耗时的监控数据和周环比数据,根据推送内容进行数据波动解读,使得我们对于性能问题更加具有主动性,能够及时发现明显性能问题。

Step4:性能问题解决

当视角聚焦于各单一性能指标时,由于不同的指标所在的场景各不相同,各个指标对应的性能问题的定义&分析&解决通常需要结合实际业务场景进行确定和分析。首先,性能问题的定义可以基于两个方面:1、性能指标数值是否符合预期;2、性能指标波动是否存在异常,如何定义符合预期的性能指标和正常的波动范围可根据实际情况确定口径。当确定性能问题的定义后,出现满足性能问题定义的情况时,我们基于性能指标的统计口径进行分析,前/后端或者前后端配合一起结合业务逻辑进行梳理排查,在分析过程中前端可以通过 Chrome Performance 工具查看代码执行情况,此外还可以关注性能指标所涉及的后端接口的波动情况是否与性能指标波动一致。对于性能问题的解决,造成页面性能问题的原因有非常多,绝大部分的问题不是前端渲染瓶颈,就是后端接口访问瓶颈,例如前端渲染卡顿常见就是大数据量的内容需要渲染引起的卡顿,通用方法可参考 👉 “大数据量场景下前端的性能优化方案 - 掘金”,前后端对于性能优化的方法也有非常多内容,此处不再展开介绍,同时有些性能问题单从代码层面是无法解决的,还需要产品配合进行优化设计。

总结

Untitled 1.png

我们对所有页面分级,重点关注优先级更高的核心页面,并进行用户体感耗时和关键交互耗时埋点上报,基于所确定的性能指标和对性能指标的监控指标,进行看板配置,通过看板来观察性能的波动情况,除了看板的搭建之外,还每周进行性能指标的周报推送,以周维度进行解读,两相结合及时发现异常波动从而快速响应问题。通过监控+发现+分析+解决+再监控的流程,对性能情况实现一个可持续性的良性循环:

  1. 【页面性能埋点】前端在代码中根据需要进行性能埋点并上报;
  2. 【监控性能数据】确定监控指标并通过不同形式进行性能监控;
  3. 【发现性能问题】性能指标较差或监控指标出现异常波动则发现问题;
  4. 【分析性能问题】前后端同学去分析所涉及场景的指标耗时异常原因;
  5. 【解决性能问题】根据分析出的原因制定相应的措施进行优化并上线;
  6. 【重新观测指标】性能问题解决后观测优化后的指标情况,同时持续监控其他性能指标,持续优化实现闭环。

通过前端性能埋点&监控体系的建设,我们产出性能报告以及接口耗时,先看清问题再入手,由点及面分析问题,并制定解决方案推动解决,做到性能数据的可量化和优化效果的可量化,同时根据监控指标持续监控跟进,以防止裂化,及时发现页面性能变差的趋势,更具有主动性。