一、前言
关注用户体验,提高页面性能,是每位前端研发同学的日常工作之一。提高页面性能对业务的帮助,虽不易衡量,但肯定是利远大于弊。如何衡量页面性能优劣?如何帮助研发同学快速定位到页面性能瓶颈点?一直是前端的重点工作之一。本文分享汽车之家在页面性能监控建设方面的部分工作,主要包含三方面:
整合选中技术方案,构建体系化性能监控架构,提供性能监控和性能分析工具链,支持产研同学在 DevOps 各阶段中发现和定位页面性能问题。
有数据,我们才能度量;有评分,技术才好改进。
利用采集到的众多指标,根据应用特性,按各性能指标的重要程度,设置不同的基线和权重,以加权平均的方式,求得应用得分。通过分数,直观告诉研发同学应用页面快或慢?应用性能高或低?是否需要改进?
应用得分只能反映单个应用的性能情况,主要服务于产研同学。一家公司有多个部门,每个部门有多个团队,一个团队有多个应用,我们需要公司、部门和团队层级的性能得分,才能让各级领导直观了解其负责队伍的页面性能,也方便上级领导判断下级各队伍之间的性能高低,所以我们根据应用 PV 数和应用级别,仍以加权平均算法,获得团队、部门和公司性能得分。
根据监控页面性能时的运行环境,我们将技术方案分为两种:合成监控(Synthetic Monitoring,SYN)和真实用户监控(Real User Monitoring,RUM)。
指在通过仿真环境运行页面,评估页面性能。早期代表工具有我们熟知的 YSlow 和 PageSpeed。随着技术进步,当前三个最成熟的 SYN 工具为:Lighthouse、WebPageTest 和 SiteSpeed。Lighthouse 虽然仅支持 Chrome 浏览器、实施成本较高,但是有谷歌支持、易扩展、指标丰富、有评分诸多优势,已逐步代替 WebPageTest,成为 SYN 首选工具。 如下以 Lighthouse 为例介绍 SYN 的运行过程、优缺点。
从运行结果页面来看,Lighthouse 除了输出关键性能指标值和评分外,还向我们提供优化建议和诊断结果。10.1.0 版 Lighthouse 分别内置 94、16 条性能和最佳实践方面的规范或建议,其中不乏日常研发比少留意且较有意义的规范,如:最大限度地减少主线程工作(mainthread-work-breakdown)、网页已阻止恢复往返缓存(bf-cache)、减少 js 文件中未使用的 JavaScript (unused-javascript)等。
推荐使用 Node Cli 或 Node Module 方式运行 Lighthouse,同时输出 html 和 json 格式的结果。json 中数据更全面,包含如:最大内容渲染时间元素(largest-contentful-paint-element)、应避免出现长时间运行的主线程任务(long-tasks)等明细信息。
根据我们实践,总结 Lighthouse 有如下优缺点:
针对上述不足和产品需求,我们做了一些改进:
n为解决 默认无基准环境,相同页面在不同用户端运行,因运行环 境和硬件资源不同,导致结果不同的问题,我们做了两方面的改进:
首先,提供 SYN 基准运行环境。利用 Lighthouse Node Module 自研 Web 版 SYN 服务并部署在容器中。通过在 Node 服务端添加队列策略,保证单容器任意时间只允许运行一个 SYN 任务,且每个容器的硬件资源( 4 核 + 4G )和网速配置( M 端应用统一使用 10M 网速 )都一样,从而保证运行结果和最终得分是相对公平和可靠的。
其次,支持以计划任务,间隔 6、12 或 24 小时 的方式运行 SYN 任务。 统计多次运行结果指标的 AVG、TP 值,排除少数异常运行的结果偏差。
SYN 实施成本低,便于统一标准,相比 RUM,受运行时环境的影响更小,结果更具有可比性和可复现性,是性能监控的重要一环。基于 Lighthouse,借助 K8S 等容器编排技术,快速搭建提供基准环境的 SYN Web 服务是建设页面性能监控体系的第一阶段。该阶段以提供评估页面性能、分析慢页面等关键功能为主。虽然 Lighthouse还存在 仅支持谷歌浏览器,代表性不足,也不能真实反映真实用户端的性能情况这两个问题,但瑕不掩瑜,可以作为 SYN 的首选方案。同时,这两个问题我们将通过添加另外一种技术方案:真实用户监控(RUM)来解决。
顾名思义,指监控运行在真实用户终端(浏览器),采集用户运行页面时候真实的性能指标。业内技术方案主要分为两种:
依托 W3C 组织且各浏览器厂商广泛支持技术方案:PerformanceTiming 和 PerformanceNavigationTiming。偏向从浏览器处理过程角度去衡量页面运行时各节点、各阶段的耗时。
各厂根据实际需求自研技术方案。谷歌 web-vitals 是其中最优秀的代表,它从用户体验角度,用更通俗易懂的指标展现页面性能。
除上述两种常见技术方案外,少数商业前端监控服务厂商,除了支持 W3C 和 web-vitals 外,还提供少数自定义性能指标,如:阿里 ARMS 中的 FMP、字节 WebPro 里的 SPA_LOAD。SPA_LOAD 用于评估 SPA 非的页面性能,有较大创新性,后面还会提及。
技术选型主要解决两个问题:1)W3C 的 PerformanceTiming 和 PerformanceNavigationTiming 两规范,应该以哪个为主?2)W3C Timing 规范 和 web-vitals 应该如何协作?
W3C 的 PerformanceTiming 和 PerformanceNavigationTiming 两规范,应该以哪个为主?
PerformanceTiming: 已被最新 W3C 标准废弃,不过当前主流浏览器仍支持,旧浏览器支持好,兼容度高。
:最新标准随 Navigation Timing Level 2 于 2019 年推出,Navigation Timing Level 2 目的是代替涵盖 PerformaceTiming 的 Navigation Timing Level 1。
变更点:
优点:
缺点:
结论:
从 Can I Use 统计两者兼容度仅差 2.67%,但是从我们实际用户分布来看,使用 PerformanceNavigationTiming,用户兼容度下降 12%,难以接受。所以我们以 PerformanceNavigationTiming 为主,如浏览器不支持,则使用 PerformanceTiming。两者数据格式差异不大,忽略 PerformanceTiming 中 domLoading 节点,使用 PerformanceTiming 时认为浏览器不兼容 workStart 节点即可。
基于 W3C 规范,着重从浏览器处理过程角度衡量页面性能,以下简称 Timing。
优点:
缺点:
目前含 6 个指标:TTFB、FCP、LCP、FID、INP 和 CLS,其中 FID 将被 INP 代替。TTFB、FCP 和 LCP 反映页面加载性能,FID 与 INP 代表页面交互体验,CLS 表示页面视觉稳定性。仅 6 个指标,就能支持对页面加载、交互和视觉稳定方面的评估。不过 web-vitals 部分指标源头还是来自于 W3C 制定的 LargestContentfulPaint、LayoutShift、PerformanceEventTiming 和 PerformancePaintTiming 等规范,不过兼容性更好、整体性更强。
优点:
缺点:
真实、客观、全面衡量页面性能。
同时采集 Timing 和 web-vitals 数据,带来好处有:
RUM 技术选型,同时采集 PerformanceNavigationTiming和 web- vitals。如果浏览器不兼容 PerformanceNavigationTiming,则以 PerformanceTiming 代替。
我们的需求是:在尽可能不影响页面性能,既能客观、全面衡量页面性能,又能帮助研发同学快速定位性能瓶颈点。具体包含三方面需求:1) 指标要全面客观;2) 能发现慢页面的瓶颈点;3) 满足前面两需求前提下,尽可能不影响页面性能。
首先,我们采集了 web- vitals 六个指标,效果如下:
谷歌计划于 2024 年用 INP 替换 FID,FID 体现第一次交互的延迟时间,INP 表示所有交互中最长的延迟时间。我们认为 FID 和 INP 都有各自使用场景,同时保留并不矛盾。
其次,我们对 PerformanceNavigationTiming做了加工处理,效果如下:
所以我们结合 W3C 示例图,以点、段和线的方式,展示真实的页面运行过程:
此外,为了更全面体现页面性能,还采集和统计了如下输入:
站点统计数据,根据应用类型是 PC 或 M 来制定慢页面标准,具体阈值如下:
针对慢页面,我们除了采集上节提到的 PerformanceNavigationTiming、web- vitals、小概率的完整 PerformanceEntry 数据和统计数据外,我们还会采集:
RUM 必须通过入侵页面,在页面引入 JS SDK 来实现,不可避免地影响页面性能。作为一个发现和分析页面性能的工具,不应该加重页面性能问题。为了将性能影响降到最低,我们做了两方面工作:
异步加载 JS SDK:页面只引入功能单一、体积小的 JS 头文件,待页面到达 DomContentLoaded 事件后,以动态 script 方式异步加载功能完整的 JS 主文件。
综上所述我们采集指标主要两大类:PerformanceEntry 和 web-vitals。
SPA 应用非性能该如何评估?
采集上述指标,已经可以较为客观全面评估常规页面和 SPA 应用的页面性能。但是 SPA 应用非不是浏览器标准,在 SPA 路由切换过程中:
所以,对于上述指标 SPA 非无 法或无法准确拿到,所以我们暂不评估 SPA 非性能。
针对业内 SPA 非性能难评估的情况,字节 WebPro 创造性地推出 的概念,基本逻辑为:以触发 history.replaceState() 方法为起点,通过 MutationObserver 监听 dom 变更、资源加载、请求发送等变更事件来寻找一个页面达到稳定态的时间为终点,通过计算起终点之间的耗时,来衡量 SPA 非的页面性能。SPA_LOAD 类似于常规页面 onload 事件,但是起始时间比真实路由切换时间晚,到终止时间时页面可能已经加载完毕,略有不足,不过已是当前最佳的方案,后面我们可能引入。
只有采集真实、准确的指标值,才能真实反映页面性能,反之,可能误导产研同学,错误评估真实的页面性能。所以选择采集指标时机有几大原则:
那么如何确定采集时机?我们得先分析 PerformanceEntry 和 web-vitals 两类指标数据得准确生成时间:
对于 PerformanceEntry 数据,onload 事件触发时,页面已接近加载完毕,PerformanceEntry 中影响首屏加载的绝大部分指标数据已经生成。未生成的数据对评估页面性能影响不大,如:PerformanceNavigationTiming中的 loadEventEnd 指标值。所以我们认为 onload 事件触发件时,可以采集 PerformanceEntry 指标。
web-vitals 中各指标生成原理不一,onload 事件触发时:
考虑,我们认为至少要满足:触发 onload 事件或打开页面 5s 之一条件时,才能保证 PerformanceEntry 或部分 web-vitals 指标值准确,采集才有意义。在追求”样本多“的原则下,结合 RUM SDK 是 onload 事件后异步加载的实际情况,我们针对页面是否被正常关闭前提下,总共设置了三种采集时机,其特点如下:
为了避免采集指标影响页面性能,我们异步加载 RUM JS SDK,web-vitals 中各指标默认仅支持异步回调,异步加载再异步回调,导致采集时机时仍可能无法拿到各指标值,所以我们对 web-vitals 源码做了改造,支持同步获取各指标值。
采集到指标后,需要选择恰当上报方式,将指标可靠的发送到后端。上报方式包含两个部分:上报机制和上报时机。
选择合适的上报机制,首先,要满足功能需求,浏览器兼容度高,对数据大小最好没限制;其次,能感知上报请求异常,便于上报重试,进而提高上报可靠性;最后,客户端支持设置超时时间,避免长时间占用忘了连接,加大后端服务压力。常见上报机制有四种,分别是:Image、XMLHttpRequest、sendBeacon、Fetch API。其特点如下:
创建一个 1 像素、隐藏的 img DOM,将上报地址和上报内容包含在 img 的 src 中。上报成功则返回 200 状态码 |
利用浏览器内置对象 XMLHttpRequest 上报数据 |
使用专门设计用于发送分析数据的 navigator.sendBeacon()方法,以异步发送 HTTP POST 请求的方式将分析数据提交到后端 |
fetch 是一个现代的、基于 Promise 的用于发送 HTTP 请求的 API |
各浏览器大小限制不一,且受制于 CDN、后端代理和 web 服务器,默认值常为 8K。8K 指用 URI 编码后的长度 |
|||
请求返回状态码为 404 或 204 时会触发 img onerror 事件。状态码大于等于 ,不会触发 onerror 事件,如 、500、502 和 504 等。 |
sendBeacon()返回值,只能表示浏览器是否发出请求 |
||
不可以,依赖服务端的设置 |
|||
相比于 XMLHttpRequest,使用更简介、功能更强大 |
|||
数据大小有限制,难感知上报异常 |
无法感知上报异常,函数返回值 true、false 只能代表是否发送成功 |
||
上报数据小,可靠性要求不高 |
建议以 POST 方式用 text/plain 或 application/x-www-form-urlencoded 格式上报,CORS 预验证 |
需要在页面关闭时,上报数据 |
同 XMLHttpRequest,更适用于浏览器分布较新的终端 |
相比于 Fetch,XMLHttpRequest 功能几乎一致,兼容性更高;与 Image 对比,XMLHttpRequest 具有兼容度高、数据大小没限制、能感知异常和可设置超时时间等优势;XMLHttpRequest 是页面正常(未关闭)情况下,发送指标数据的首选上报机制。至于 sendBeacon,虽然存在诸多不足,但是页面关闭时仍可以上报数据,成功率还较高,适合作为在页面关闭时,发送尚未发送的指标数据的上报机制。
既然选择了 sendBeacon 作为页面关闭时发送指标数据的上报机制,那该如何判断页面被关闭?传统方案是监听 unload 或 beforeunload 事件,该方案存在两个不足:
更合适、更现代的方案是监听 pagehide 或 visibilitychange===hiden 事件,该方案除了避免传统方案存在的两不足,兼容度也会更高。对于 SPA 项目我们不采集非性能指标,触发History.replaceState()方法也算离开页面。
综上所述,整体上报机制为:1)页面正常(未关闭),到采集时机时,SDK 采集性能指标数据,使用 XMLHttpRequest 机制上报;2)通过监听 pagehide 或 visibilitychange===hiden 事件,当页面被关闭时,如果满足任一采集时机条件,则立即采集指标,使用 sendBeacon 机制上报。
综上所述,我们整理 RUM 实施大纲如下:
实际编码过程中,具体处理流程如下:
在实施过程中,我们总结 RUM 优缺点如下:
RUM 架构设计复杂,实施成本较高,由于是技术刚需,只能投入资源,努力做好。
针对 无诊断结果和优化建议的缺点,可以结合 SYN,取长补短,利用 SYN 诊断慢页面性能瓶颈点分布。
对于 无评分,没法判断页面性能优劣的问题,我们分三步走:首先,制定慢页面标准,判断单次页面是否快慢,标准值前文已有描述;其次,统计该页面各重要指标的 AVG、TP50、TP90、TP99 值,全面评估页面所有请求的性能分布;最后,我们会对页面所在的应用进行评分,直接告诉研发同学,该应用性能优劣,应用评分具体做法,会在下面《建立评分体系》章节细讲。
前文深入分析了 SYN 和 RUM 各自特点、使用方法及优缺点等,我们发现 SYN 和 RUM 各有所长、无法替代,最好同时引用 SYN 和 RUM,构建体系化性能监控架构,提供性能监控和性能分析工具链,支持产研同学在 devpos 各阶段中发现和定位页面性能问题。
在编码、构建和测试阶段,研发同学可以利用 SYN 来做页面性能测试,判断页面性能是否达标?如果页面性能有问题,再利用 SYN 诊断性能问题,获得优化建议。此举解决前端页面长期以来,前端页面做性能测试难、交付页面质量无标准等痛点。应用部署后,再利用 RUM 采集真实用户页面性能,评估真实页面性能,如果还存在慢页面,仍可以使用 SYN 定位慢页面性能瓶颈点,并利用诊断结果和优化建议,提高优化效率。除此之外,SYN 还可以用来做竞品对比,达到知己知彼、快竞争对手一步的目的。
有了 SYN 和 RUM,我们可以构建在线持续优化慢页面的闭环,如上图。RUM 负责采集真实用户产生的慢页面,经后台存储、聚合,自动将 TOPN 的慢页面创建 SYN JOB,待 JOB 运行完毕,将诊断结果和优化建议以告警防止通知研发同学,研发同学利用 SYN 优化建议,再利用 devtools、webpack 等工具,改进页面,交付高质量页面,降低慢页面的频次。如此循环迭代,持续优化应用页面性能,最终应用能达到极致性能。
引入 SYN,自研 RUM SDK,采集到众多 SYN 和 RUM 指标数据后,我们将着手建立评判体系,评估各应用、团队、部门,乃至整个公司的性能情况,输出少数几个关键指标和评分,直观告诉各层级、各角色员工其所在组织及同级组织的页面性能情况,通过得分和同级对比,评判是否要优化页面性能?
建立评判体系时我们秉持着:既要突出重点、关键指标,同时还能全面、综合、客观真实地反映页面性能 的原则。所以我们将评判体系分为两大块,其一,展示最关键的性能指标。其二,输出各指标、应用、团队、部门及公司层级的性能评分和层级。
展示最关键的性能指标
我们从 web-vitals 和 performanceNavigationTiming 中各选一个最能代表页面性能的指标,分别为:DCL 和 LCP。LCP 兼容度不高且可能被伪造,DCL 既能代替 LCP 部分反映首屏性能且兼容度高、难以伪造,和 LCP 相辅相成,最能体现页面性能。
TP90 代表 90%用户的体验下限,与 AVG、TP50、TP75 比,覆盖和统计更广的用户,还能屏蔽页面在手机端特殊网络环境下,产生的少数脏数据,更具有代表性。
为了全面、综合和客观的评估应用页面性能。我们将选择各维度具有代表性指标,参考 HTTP Archive 给予的业内指标分布,根据应用特性,如应用类型( PC 或 M 端 )、终端用户( C 端用户、B 端客户和内部员工),设立不同的评分基线,算出各指标得分。再根据各指标重要程度设置权重,通过加权平均算法,求得应用性能评分。流程如下:
获取应用性能分过程中涉及几个重要流程:1) 指标筛选及权重设置;2) 选择评分算法;3) 确立指标基线;4) 使用加权平均算法计算应用性能分。下面逐一介绍。
此过程中,我主要考虑两点:
全面综合考虑。页面性能涵盖多方面,传统上只用首字节、白屏、首屏时间等少数指标来衡量,较为片面,不够客观。我们认为评判页面性能应该涵盖各维度指标,如:页面加载、交互体验和视觉体验。此外我们还引入慢 API 比例的概念,API 请求比例指页面打开后 API 耗时超过 3s 的请求比例,慢 API,即可能影响首屏加载耗时,也会影响交互过程中的用户体验。为了让研发同学关注慢页面、将在线 SYN 作为日常开发性能评估工具,我们将 SYN 评分也作为权重指标,后台系统每天会统计访问次数 TOP10 的慢页面并自动创建 SYN 定时任务,待任务执行、分析完毕后,将优化建议和诊断结果通知研发同学。SYN 评分项,包含性能分和最佳实践分,两者都是百分制。
突出重点。提高重要指标的权重比。如:加载指标用于衡量页面能不能用,最为关键,所以赋予权重占比最大。LCP 是最重要的加载指标,权重占比也相应提高。由于 LCP 本身不一定完全合理且可能被伪造,所以评判页面加载性能时,还引入 DCL、FCP、TTFB、WindwLoad 和 PageLoad 等加载指标。该做法,优点:指标多,维度广、角度大、更全面和更客观准确;缺点:增加评判系统复杂度和难度。
基于上述两点考虑,我们指标筛选结果和权重占比设置,如下图:
各指标以其 TP90 统计值,参与评分运算。
评分算法主要参考 Lighthouse 评分曲线模型,基本原理是:设置两个控制点,通常是 TP50 和 TP90,即得 50 或 90 分时的指标值点,然后根据这两个控制点,生成对数正态曲线,通过该曲线可以获得任一指标值对应的得分。下图是 M 端 LCP 的评分曲线:
m 表示中位数,图中 m 值为 0ms,表示当 LCP 值为 0ms 时,得 50 分;同理 p10 为 2520ms,LCP 值为 2529ms 时,得 90 分。设置 m 和 p10 后,会生成右边的评分曲线模型,根据该模型可以获得 LCP 值从 0 到正无穷时的得分。
确立指标基线是为了给评分算法提供两个控制点,即 m 和 p10 的值。确立方法有三种:
确立基线过程中,应考虑应用价值和研发要求的不同,根据应用特性,有针对性的设置。首先,PC 端和 M 端类型的应用,要设置不同的指标基线,所幸 Lighthouse 和 HTTP Archive 都提供 PC 端和 M 端的配置参考;其次,根据应用实际终端用户类型,有针对性的调整阈值。C 端和 B 端应用,直接产生业务价值,性能要求要比内部应用高,两控制点值应该更低。
使用加权平均算法计算应用性能分
根据指标 tp90 值、指标基线和评分算法,求得该指标的百分制得分。
使用加权平均算法求应用性能分,结果 = (Σ (指标tp90值 × 指标权重)) / (Σ 权重) ,其中:Σ 表示求和。
至于求各级组织,含团队、部门及公司的性能分,则根据其管辖的应用个数、应用性能分及应用权重,仍使用加权平均算法获取组织分。流程如下:
求组织性能分的难点是:如何设置应用权重?我们主要参考应用的 PV 区间和应用级别。PV 层级越大、应用级别越高,权重越大。具体配置参考如下:
PV区间中的PV 值指采用 PV,而非真实 PV,采用 PV=采集到 RUM 数据量/抽样比例。
经过上述步骤,我们能获得应用性能分,以及各级组织的性能分,如团队性能分、部门性能分及之家性能分,展示效果如下:
性能分参考lighthouse标准,50分以上算合格,90分以上才算优秀。
通过页面性能监控和评判体系建设,我们既有原始页面性能数据,又有聚合统计值,还有最终评分。通过评分、统计和原始数据,打通了发现、定位和分析性能问题的链路。研发同学可以通过评分直观判断应用性能优劣是否需要优化?如果需要优化,再通过聚合统计数据,分析应用瓶颈点;定位具体瓶颈点时,可以查看明细数据,辅助分析产生瓶颈点的具体原因;改进后可以通过通过统计查看优化效果,最终反映到提高评分上。
受限于篇幅,本文仅能介绍页面性能监控和评判体系建设相关的实践。一个完整的页面性能监控系统,还应该包含:监控、报警、优化、治理等模块,不仅仅只是指标,能度量页面性能,发现其中性能瓶颈点,帮助研发同学提升优化效率,还要治本,通过构建一系列前端工具链,改进交付过程,通过规范、工具和流程,从源头上提高页面交付质量,避免将问题带到线上,先于用户发现性能问题。
一个收集和分析网站性能数据的项目,旨在帮助 Web 开发者了解互联网的技术趋势以及性能优化的最佳实践。
本网站的文章部分内容可能来源于网络和网友发布,仅供大家学习与参考,如有侵权,请联系站长进行删除处理,不代表本网站立场,转载者并注明出处:https://jmbhsh.com/yulebagua/33672.html