大道至简:万字漫谈前端性能监控

前言

在2025年的今天,针对xx监控这几个字眼已经有点"老生常谈"的感觉了,无论是什么数据监控、异常监控或者是本文即将要分享的性能监控,在当今他们并不是做为一种"新东西"来供大家学习,而是经常以一种"老朋友"的姿态和大家见面。

随着前端页面的日益复杂,交互、初始化等功能不断增加,性能监控已经不再是一个可选的附加项,而是开发过程中不可或缺的一部分。我们可以把性能监控比作前端开发中的"健康检查",它像是医生对页面的体检,帮助我们及时发现潜在的问题,避免那些用户体验上的"隐形杀手"。

还是那句话,谁不想让网页快一点、访问起来爽一些呢?

网站性能的影响

对用户的影响

你打开网站可以等待的时间是多少呢?你是否确定用户为了访问你的网站可以等上1秒?5秒?或者是10秒吗🤔?

就我个人来说,在访问各类网站时,如果响应时间过长的话会让我觉得很"不舒服",可能在某些PC等久点会好一些,但是如果是移动端,那简直是"无法忍受"的程度。

事实上,有统计指出加载延迟每增加100毫秒,用户满意度下降约1%,一般来说,网站响应时间2秒以内通常被认为是用户可接受的阈值,超过3秒时,用户流失率显著增加,当等待时间超过8秒 时,大多数用户会放弃访问,达到12秒则99%以上用户选择关闭网页

单纯从用户转换率和跳出率来讲,可能没法从冰冷的数字中感受出网站性能对用户流失的影响有多大,但是对于某些每年有巨大营收的公司来说,这一点点的延迟加载会对业务造成沉重的打击。

亚马逊前软件工程师 Greg Linden 曾在2006年发现每多出100ms延迟就会导致约1%销售损失,即使是非常小的延迟也会导致收入大幅下降,代价高昂。原文

对搜索引擎的影响

除了直观的对用户造成影响以外,性能因素对搜索引擎的排名也有较大的影响。

早在2010年,Google在排名算法中就已经把页面加载速度作为一个重要因素。页面加载速度越快,搜索引擎越可能给予该页面更高的排名。反之,如果页面加载缓慢,搜索引擎可能会降低其在搜索结果中的排名,导致网站流量下降。

Google在2018年发布了 "Mobile-First Indexing" ,即优先使用移动版内容来进行排名。如果网站在移动端加载缓慢或者交互体验差,搜索引擎会优先降级该网站的排名,影响其在搜索结果中的表现。

总而言之言而总之,在现代开发中,想要你自己的应用在搜索引擎中脱颖而出,性能早已是不可忽略的关键因素。

对开发和维护成本的影响

如果不在开发初期就关注性能,后期可能会积累大量的技术债务,增加维护难度。性能问题往往表现为页面响应慢、资源加载失败等,这些问题如果没有及时解决,可能会成为日后开发迭代的阻碍。

性能监控的两种方案

即使性能监控这个话题已经广泛讨论过,但随着技术演变,它也需要不断地更新进化。如今,性能监控不仅仅是用来检测页面加载是否顺畅,还承担着预警、数据分析和优化决策等多重角色。

性能监控分为两大类:合成监控真实用户监控

合成监控

合成监控(Synthetic Monitoring, SYN)是通过模拟用户的行为来评估网站或应用的性能 。模拟用户可以是脚本或专用工具,它们在指定的时间间隔内发起请求,模拟实际用户访问,并通过预定的测试场景收集各种性能指标。SYN监控通常用于检测性能瓶颈、服务可用性、响应时间等指标,适用于在没有真实用户流量时进行监控

开发中我们可以用市面上较为成熟的合成监控工具进行测量,知名度比较高的应该还属LightHouseGoogle Pagespeed Insights

假设我们现在想用LightHouse来监测React官网的性能如何,我们可以先本地安装一下LightHouse:

powershell 复制代码
npm install -g lighthouse

这里指定监测网站并将报告输出为HTML文件:

powershell 复制代码
lighthouse <https://zh-hans.react.dev/> --output html --output-path ./report.html

监测结果页差不多长这样:

从LightHouse生成的结果来看,React官网看起来不是很"好",那是否证明React官网真的不够好呢?实际未必。

合成监控是存在局限性的。

不同工具对性能指标的重视程度不同,这意味着不同的工具监控指标很可能权重不一致,监测方法也会存在一定的差异 。如某些工具侧重页面加载时间,而其他工具可能更关注交互延迟等。另外,工具使用的测试环境、设备性能、网络状况和浏览器版本也有所不同,进一步影响了监测结果的准确性。因此,同一网站在不同合成监控工具下可能会得出不同的性能评估数据

总结来说:

合成监控有一些显而易见的优点:

  1. 实现简单,解决方案成熟
  2. 可以采集到更丰富的数据
  3. 不影响真实用户的访问性能
  4. 提供多种可视化分析

但同时合成监控也仍存一些局限:

  1. 无法真实还原所有场景,考虑因素较少
  2. 登陆等场景需要额外解决(强制登陆页或管理平台页)
  3. 单次执行数据不稳定,数据量过小

真实用户监控

真实用户监控(Real User Monitoring, RUM)是通过收集实际用户在访问网站或应用时的性能数据来评估性能。RUM 监控不依赖于模拟用户或脚本,而是直接从用户的设备中获取数据,捕捉他们的交互行为和页面加载时间。

通常来讲,在看NetWork里面的请求时,有一堆看不懂的字符串一般都是内容上报hh

下面是一个真实用户监控的流程:

真实用户监控看起来very good,毕竟是基于"真实"的数据进行监控,但是真实用户监控也存在一定的局限性,主要体现在数据的代表性和采集的复杂性上。

由于 RUM 是基于实际用户的行为进行监测,因此不同用户在不同设备、网络环境和地理位置下的体验差异可能导致数据的不一致。由于用户行为多样性,RUM 无法在短时间内提供全面的性能评估,尤其是在流量较小或访问量较低的情况下,数据可能存在一定的偏差,不足以支撑性能分析的全面性。

总结来说:

真实用户监控有一些nice的点:

  1. 无需模拟,完全还原真实场景
  2. 不存在登陆等需要额外解决的场景
  3. 在数据量足够庞大时,分析结果总是好的

但是也存在一些bad点:

  1. 可能会影响真实用户的使用感受
  2. 无法采集硬件相关指标
  3. 无法采集完整的资源加载瀑布图(现代平台其实很多都可以)
  4. 无法可视化展示页面的加载过程(现代平台其实很多也都可以)

如何选择合适的方案

  • 合成监控 更适合在开发阶段上线前做性能优化,帮助发现一些潜在的性能瓶颈,并且不依赖真实用户的访问量,适合做定期的监控和预警。
  • 真实用户监控 更适合用来持续监控 网站或应用的性能,并且可以了解不同用户群体在真实环境下的使用体验,尤其对于大规模的实时监控跨设备跨网络环境的表现非常有帮助。

真实用户性能数据的采集方案

ps:合成监控的知识相对比较单一,常用的工具基本都是开箱即用。结合实际来讲,开发中其实更多是需要我们掌握的事真实用户性能数据的采集和分析,这里和大家分享一下RUM的相关内容:)

Performance API 介绍

在JS中,主要进行性能数据采集的API都属于浏览器提供的Web Performance API的范畴,基于用途可以分为以下八类:

写在前面: 原生的PerformanceAPI固然很好,但是实际业务中使用的时候还要结合实际情况分析。 抛出一个引子:例如你的页面首先展示Loading态,你的业务中并不认为Loading态加载出来时是第一个元素加载的时间(可能以页面业务元素为准),但是默认一些API会认为Loading态就是"理所应当"的第一个元素。 所以说也不要一把梭哈就用PerformanceAPI一条路走到死噢~

这里着重介绍三个重要用途/过程,分别是Performance DataNavigation TimingResource Timing

下文主要是分享用途,用一些常用API来增强对特定内容的理解,有些用途中的API说的可能不完全,感兴趣的话还是自查MDN~

Performance Data

Performance Data 是整个Web性能监控的基础核心,它做为其他所有用途的基石,它主要回答三个问题:

  1. 浏览器有哪些性能可以拿?
  2. 怎么拿?怎么监听?
  3. 怎么处理这些拿到的东西?

在我们知道哪些性能可以拿的时候,我们首先要先知道性能数据从哪里来?

实际上,浏览器内部维护了一个性能条目队列 ,每当页面加载、资源加载、用户交互、开发者打点等事件发生,都会记录对应的性能数据,存储为不同类型的 PerformanceEntry 对象。

这些性能数据通过统一的接口 performance.getEntries()PerformanceObserver 提供给开发者。

每个性能数据条目都属于某种"类型",这些类型表示它是关于什么的性能数据。

类型(entryType 描述 举例
"navigation" 页面整体加载的性能数据 首次加载页面的流程
"resource" 页面上资源加载的性能数据 加载图片的耗时
"paint" 首次绘制相关指标 FP、FCP等
"mark" 自定义的起始时间点 performance.mark('start')
"measure" 自定义的耗时段 performance.measure('duration', 'start', 'end')
"longtask" 超过 50ms 的长任务 主线程卡顿情况
"largest-contentful-paint" 最大内容绘制时间 LCP
"first-input" 首次交互的响应延迟 FID
"layout-shift" 页面布局变化 CLS

可以通过performance.getEntriesByType("xxx")获取对应的数据,在控制台试一试!

上面我们所说的获取性能资源条目 实际上并不够灵活,如果你希望实时监听性能事件(比较经典的是LCP、资源加载等),使用PerformanceObservers是最佳方式。

例如:

js 复制代码
const observer = new PerformanceObserver((list) => {
  list.getEntries().forEach(entry => {
    console.log("实时观察到的性能数据:", entry);
  });
});

observer.observe({
	// 设定监听的资源条目
  entryTypes: ["paint", "resource", "mark", "measure"]
});

在现代性能监控中,PerformanceObserver早已成为构建RUM的系统的核心组件了。

到这里我们已经"替"Performance Data回答了两个问题了,第三个问题详见后续:分析性能数据及影响因素。

Performance Data 这一部分,主要就是表述如何从浏览器性能引擎中提取各种"关键时刻"的数据,并将其用于性能分析、优化与监控

Navigation Timing 主要关注整个页面的导航过程,对于单个资源(例如图片、脚本等)的加载时间没有详细的度量。

下面是2012年W3C发布的第一版的Navigation Timing的处理模型:

详情见:W3C Navigation Timing Level 1

Level 1 提供了统一的 API,允许开发者在不同浏览器和平台上以一致的方式获取页面加载的关键时间点,方便性能分析和比较。

它涵盖了从重定向、DNS 查询、TCP 连接、请求发送、响应接收,到 DOM 解析和加载事件等多个阶段,帮助开发者定位性能瓶颈。

Level 1的核心接口是PerformanceTimingPerformanceNavigation ,分别通过performance.timingperformance.navigation 来访问。

Level 1 的优点非常明显:

  1. 高标准的API

    将页面导航的各类时间信息内容进行集成

  2. 细粒度的时间点

  3. 促使开发人员进行性能优化

    页面数据摆在你的面前,迫使你对耗时处进行修改优化

虽然 Level 1 在很多方面已经做的足够好了,但是仍然存在一定的局限性:

  1. 数据粒度有限

    虽然时间点比较多,但是对于更加更加细粒度的资源加载和用户交互性能指标支持仍然有限,在应用越来越复杂的场景下无法满足性能分析需求

  2. 需要使用多API处理同一个逻辑

  3. 隐私和安全限制

    出于安全和隐私考虑,某些时间点在跨域请求中可能不可用,导致数据不完整。

不得不承认,Level 1 是网页性能测量领域的重要里程碑,它为开发者提供了基础且标准化的导航时间数据,极大地推动了前端性能优化的发展。但随着需求的提升和技术的进步,Level 1 的功能已显不足,它无法处理多种场景下的复杂情况,使用它的同时通常要结合其他性能API一起使用,这样才可以获得更全面和精细的性能分析能力。

所谓长江后浪推前浪 一浪更比一浪强~ Navigation Timing Level 2 应运而生

下面是W3C第二版的Navigation Timing的处理模型:

详情见:W3C Navigation Timing Level 2

Level 2 是对 Level 1 的扩展和改进。

从图中不难看出,Level 2 相较于 Level 1 有更多的时间节点、更灵活的接口设计、更丰富的测量指标、更强大的跨域资源的处理、更权威的配色、更兢兢业业的提出人员...

针对 Level 1 的局限性,Level 2 做了一些优化:

Level 1 的局限性 Level 1 的局限性细则 Level 2 的优化
数据粒度有限 时间点多,但缺乏对资源级别和用户交互的详细度量。
时间精度以毫秒为单位。 时间点更为丰富(继承了Resource Timing),方便结合现代网页进行更全面的剖析。
时间精度以微秒为单位。
需要使用多API处理同一个逻辑 需要使用PerformanceTimingPerformanceNavigation 将所有导航相关指标整合为单一对象 。只需使用PerformanceNavigationTiming即可
隐私和安全限制 跨域请求中某些时间点不可用,可能导致数据不完整 增强了对跨域资源的性能数据暴露支持,在保障隐私的同时提供了更精细的资源数据监控,减少数据泄露的风险。
支持 PerformanceObserver 监听

Level 1 的时间精度是以毫秒为单位,基于Date.now(),如果修改系统时间,Date.now()会跟着变化;Level 2 是名副其实的高精度(High Resolution Time, HRTime)时间,所有时间戳基于performance.timeOrigin ,以微秒精度为准,不会随着系统时间的修改而变化的

由于只包含当前文档,因此通常只有一个 PerformanceNavigationTiming 对象可供观察。它扩展了 PerformanceEntry 接口,entryType"navigation" ,并且继承自PerformanceEntryPerformanceResourceTiming,因此获取文档过程中可以使用指定性能资源条目的方式,所有时间戳也都可用。

我们可以通过一个小例子来直观看出二者从使用角度上的区别:

现在提一个最最最ez的需求:监听浏览器的load事件,计算并打印页面的加载时间。

js 复制代码
window.addEventListener('load', () => {
  // Level 1
	const timing = window.performance.timing;
	const loadTime = timing.loadEventEnd - timing.navigationStart;
	console.log('Level 1 页面的加载时间为:', loadTime, 'ms');

  // Level 2
  const navEntries = performance.getEntriesByType('navigation');
  if (navEntries.length > 0) {
	  const navTiming = navEntries[navEntries.length - 1];
	  const loadTime2 = navTiming.loadEventEnd - navTiming.startTime;
	  console.log('Level 2 页面的加载时间为:', loadTime2, 'ms');
	}
});

这里有一个需要区分的点,即使Level 2 采用了更高的时间精度,最终输出结果也仍然转换为毫秒。因为浏览器内部的性能时间戳通常都使用毫秒级别

两段代码实现的功能是一致的,随便找一个网页的控制台进行测试:

可以很直观地看到,Level 2 的加载时间的精度更加Good。

稍微复杂一点点,Level 1 就无法"只"使用PerformanceTiming独自胜任。

假设你想获取页面加载的详细时间 ,并且需要知道页面是否是从缓存加载的,以此来优化性能。

在Level1中你需要将PerformanceTimingPerformanceNavigation结合来使用:

js 复制代码
window.addEventListener('load', () => {
	// PerformanceTiming
	const timing = window.performance.timing;
	const loadTime = timing.loadEventEnd - timing.navigationStart;
	
	// PerformanceNavigation
	const navigation = window.performance.navigation;
	const isFromCache = navigation.type === window.performance.navigation.TYPE_BACK;
	
	console.log(`页面的加载时间为: ${loadTime}ms`);
	console.log(`页面是否从缓存加载: ${isFromCache ? '是' : '否'}`);
});

在Level2中你只需使用PerformanceNavigationTiming即可:

js 复制代码
window.addEventListener('load', () => {
	// PerformanceNavigationTiming
	const navigationTiming = performance.getEntriesByType('navigation')[0];
	const loadTime = navigationTiming.loadEventEnd - navigationTiming.navigationStart;
	const isFromCache = navigationTiming.type === 'back_forward';
	
	console.log(`页面的加载时间为: ${loadTime}ms`);
	console.log(`页面是否从缓存加载: ${isFromCache ? '是' : '否'}`);
});

很明显本着减少代码复杂的角度,Level2更胜一筹。

再稍微复杂一点点:假设我们需要实时监听用户每次页面导航的性能数据收集微秒级别高精度的加载指标 ,并能区分导航类型(首次打开、刷新、返回等)。传统 Level 1 只能在页面加载完成后获取一次静态数据,且时间精度较低,无法满足在线监控要求。

在Level2中,我们可以结合PerformanceObserver来使用:

js 复制代码
const navObserver = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  entries.forEach(entry => {
    if (entry.entryType === 'navigation') {
      console.log('导航类型:', entry.type);
      console.log('重定向次数:', entry.redirectCount);

      // 精确微秒级时间戳
      console.log('Fetch Start:', entry.fetchStart);
      console.log('DOM Interactive:', entry.domInteractive);
      console.log('Load Event End:', entry.loadEventEnd);
      //...

      // 关键指标计算
      const backendTime = entry.responseStart - entry.requestStart;
      const frontendTime = entry.loadEventEnd - entry.domInteractive;
      console.log(`服务器响应时间: ${backendTime.toFixed(3)} ms`);
      console.log(`前端处理时间: ${frontendTime.toFixed(3)} ms`);

      // 后续处理...
    }
  });
});

// 开始监听and确保捕获页面加载前的记录
navObserver.observe({ entryTypes: ['navigation'], buffered: true });

不得否认,虽然 Level 1 官方已经不建议使用了,但是我相信很多项目还是使用的 Level 1 提供的performance.timing ,主要就是两点:

  1. 兼容性强

    毕竟H5时代就存在,所有主流浏览器都支持

  2. 简单场景下 Level 1 足够用了

    虽然精度低 并且无法通过PerformanceObserver实时监听,但是已存的字段可以满足大部分需求,并且不是所有场景都对"精度"和"实时"要求太高

所以说,即使 Navigation Timing Level 2 提供了更精细、统一的性能条目系统,Level 1 仍在许多项目中"顽强地存活"着,特别是在需要广泛兼容性和低维护成本的场景下。

但是这影响你了解并熟知 Level 2 嘛?我觉得不。很多知识都面临这个问题,我始终觉得跟进稍微"新"一些的东西并无坏处,至少我们能从"新"的东西中知道"老"的东西哪里有一些不好的地方,也可以知道所谓"新"东西有什么好的地方,这本来就是一个仁者见仁智者见智的问题。

Resource Timing

Resource Timing 同样也是性能分析中非常重要的一部分,它允许开发者详细了解页面中各类资源 (如图片、脚本等)的加载性能。它的核心接口是 PerformanceResourceTiming,通过 window.performance.getEntriesByType('resource') 获取。

详情见:Resource Timing

它提供了详细的资源加载性能数据,如图所示。这使得开发者能够识别出哪些资源加载较慢,进而采取针对性的优化措施。与 Navigation Timing 相比,Resource Timing 能够捕获页面上每个资源的加载性能,而不仅仅是页面本身

可以使用:

ini 复制代码
// 获取所有资源的性能条目
const resources = performance.getEntriesByType('resource');
console.log(resources);

打到控制台中就是这样的效果:

这样就可以非常简易的获取到各类资源的加载信息,以便后续的上报/分析。

简化版时间线与标准发展简图

Performance API本身的API规范和对象类型/接口的名字看起来比较"混乱",这里做一个简化版的时间线与标准发展简图供理解参考(上文提到的一些已加粗处理):

规范名称 描述
Navigation Timing Level 1(2012) 提供 performance.timing 等时间戳字段,核心关注页面加载流程
High Resolution Time Level 1(2012) 引入 performance.now() 精准时间
Performance Timeline Level 1(2012) 定义 PerformanceEntry 接口,最早引入 performance.getEntries()
Resource Timing Level 1(2013) 使用 performance.getEntriesByType('resource') 获取资源加载性能
User Timing Level 1(2012) 引入 mark()measure() 并将它们作为 PerformanceEntry 出现在 getEntries()
Navigation Timing Level 2(2017) 使用 PerformanceNavigationTiming 替代老的 performance.timing,统一纳入 Timeline
Performance Timeline Level 2+ 支持 PerformanceObserver、buffered 监听等

再来一个名字很像但是并非一样的:

PerformanceTiming PerformanceTimeline
定义 一个对象类型/接口 一个API标准体系/规范
用途 页面加载时间戳 各类性能条目管理
范围 仅限页面加载 包括资源加载、绘制、自定义打点、CLS、LCP 等
API performance.timing getEntries()PerformanceObserver
status 已存在但逐步废弃中 当前性能 API 的核心基础

页面性能监控的常见指标

页面性能监控的常见指标用于衡量和优化用户在访问网站或应用时的体验。通过这些指标,开发者可以了解到页面加载过程中的瓶颈,并针对性地进行优化,从而提高页面的响应速度和稳定性

相信前端的朋友们多多少少都知道一些(不,我信你一定知道一些)常见指标,关于页面性能监控的指标大致分为四类:加载性能交互性能渲染性能网络性能

(图中仅列举部分指标)

不同大类的指标通常衡量不同的场景的性能情况,我们可以根据相应的需求进行相应指标的获取。换句话说,每个性能指标都有自己独特的衡量价值,各个性能指标理应综合全面的去分析。

用一个时序图来更直观的体现出某些指标处在的阶段:

大多数指标是我们衡量网页加载速度的重要依据,这些指标在真实监控中大多都可以通过Performance API 获取/计算,总体来讲还是相对轻松的~

封装一个简单获取RUM的类

在真实项目中,我们通常不会逐个编写性能数据的获取逻辑,因为这种方式不适合实际应用。更好的方法是通过 PerformanceObserver 进行实时监听,对所需的性能数据进行动态监控。一旦监测到相应的指标,就立即进行数据获取和处理。

这里写一个监测各类简单指标的类做个小例子:

js 复制代码
const TIME = 100;

export default class PerformanceMetrics {
  private metrics: any = {};
  private observer: PerformanceObserver | null = null;
  private promise: Promise<any>;

  constructor() {
    this.promise = this.collectPerformance();
  }

	// 开始监听
  private startObserving() {
    const observerCallback = (list: PerformanceObserverEntryList, observer: PerformanceObserver) => {
      list.getEntries().forEach(entry => {
        // 监听导航数据
        if (entry.entryType === 'navigation') {
          this.metrics.navigationStart = entry.startTime;
          this.metrics.domContentLoaded = entry.domContentLoadedEventEnd;
          this.metrics.loadEventEnd = entry.loadEventEnd;
        }

        // 监听绘制数据
        else if (entry.entryType === 'paint') {
          if (entry.name === 'first-paint') {
            this.metrics.fp = entry.startTime;
          } else if (entry.name === 'first-contentful-paint') {
            this.metrics.fcp = entry.startTime;
          }
        }

        // 监听资源加载数据
        else if (entry.entryType === 'resource' && (entry.initiatorType === 'script' || entry.initiatorType === 'link')) {
          this.metrics.resourceLoadTimes = this.metrics.resourceLoadTimes || [];
          this.metrics.resourceLoadTimes.push({
            name: entry.name,
            duration: entry.responseEnd - entry.startTime
          });
        }
      });

      // 如果重要数据收集完毕,停止监听
      if (this.metrics.fcp && this.metrics.fp) {
        observer.disconnect();
      }
    };

    this.observer = new PerformanceObserver(observerCallback);
    this.observer.observe({ entryTypes: ['navigation', 'paint', 'resource'] });
  }

  // 收集性能数据
  collectPerformance() {
    return new Promise((resolve, reject) => {
      try {
        this.startObserving();

        const checkMetricsReady = () => {
          if (this.metrics.fcp && this.metrics.fp) {
            resolve(this.metrics);
          } else {
            setTimeout(checkMetricsReady, TIME);
          }
        };

        checkMetricsReady();
      } catch (error) {
        reject(error);
      }
    });
  }

  async getPerformance() {
    return await this.promise;
  }
}

使用起来也非常便捷:

js 复制代码
import PerformanceMetrics from "xxx"
// ...
const pMs = new PerformanceMetrics()
const perf = pMs.getPerformance()
// ...
console.log(perf)

后续我们可以根据获取到的指标进行分析处理...

数据上报的维度

这里我们不说具体的上报方法,而是来说一下数据上报的维度。

为了确保我们RUM分析的全面性,有时仅有这些性能指标的数据是远远不够的,还需要从多个维度综合考虑。数据上报的维度可以分为常规维度特殊维度。

常规维度

常规维度具有普遍性和基础性,适用于大多数的数据收集和监控场景:

特殊维度

这些维度主要用于特定的应用场景或者进行深度分析时使用,通常与业务相关,或用于分析性能异常和用户行为:

分析性能数据及影响因素

数据辛辛苦苦采集到了,分析数据就别搞得草草率率的了。

时间分布

最常见的分析性能数据的切入点就是时间分布了。通常要结合平均值中位数百分位数来进行性能评估,单一分析一指标的话往往容易误判用户真实体验。

  • 如果我只看平均值

    假设网页加载时间的平均值是3秒 ,但其中少部分用户因网络条件差,加载时间可能超过10秒 。这些极端值会拉高整体平均值,掩盖了大多数用户实际较好的体验

  • 如果我只看中位数

    如果中位数是2.5秒 ,说明一半用户加载时间低于这个值。这比平均值更稳定,但依然无法体现尾部用户的极差体验

  • 如果我只看百分位数

    (你想看百分之多少呢?)

    对于高性能要求的业务,你更应该关注尾部用户的体验 ,例如P95/P99 等。(如果P95为5秒 ,意味着95%的用户加载时间低于5秒,还有**5%**用户比这慢)

所以分析性能指标时建议关注百分位数,对性能的要求越高,使用越大的百分位数,同时在关注百分位数的要结合平均值和中位数一起分析。

资源类型归类

我们也可以选择对资源类型进行归类分析,这其实也是对性能分析的一个比较重要的地方。

试想明明你想分析首页加载时间,结果相关资源直接加载失败了,甚至都加载出来,这肯定是在性能监控分析之上更不可能容忍的。

按照资源类型来分析的常见内容有:

资源 示例 部分分析
JavaScript 应用包、SDK 包体积、执行时间、长任务
CSS 主样式、字体加载 阻塞渲染、未使用样式
图片 img、icon 是否压缩、懒加载
第三方资源 广告 是否阻塞加载、错误率

缓存与加速因素标记

在分析性能数据的时候,缓存和某些加速因素也会对性能分析造成一定的"误判"影响。好比明明资源很大,加载很慢,结果浏览器缓存了,那我们此时再去监测资源的获取时间就非常"鸡肋"了。

有一些相对比较常见的因素,在分析时可以稍作留意:

  • 是否命中浏览器缓存/Service Worker
  • 是否命中CDN加速节点
  • DNS是否走了预解析

写在最后

本文讲的内容多以概念性的东西为主,算不上深入浅出不过还是希望这篇文章可以对你有一些帮助,此外,文章中相对结合实际较少,理论性的内容终究还是要通过实践来加深理解。

如果文章里有错误或者需要补充的地方可以在评论区留言,如果可以的话也可以在评论区讨论交流呀,感谢大家🙏

(如果真的看到这了,可否三连支持下呢~)

相关推荐
0思必得04 小时前
[Web自动化] CSS基础概念和介绍
前端·css·python·自动化·html·web自动化
小胖霞4 小时前
全栈系列(15)github Actions自动化部署前端vue
前端·node.js·github
未来魔导4 小时前
基于 Gin 框架的 大型 Web 项目推荐架构目录结
前端·架构·gin
foundbug9995 小时前
Modbus协议C语言实现(易于移植版本)
java·c语言·前端
Luna-player5 小时前
在前端中list.map的用法
前端·数据结构·list
听风吟丶5 小时前
Java 反射机制深度解析:从原理到实战应用与性能优化
java·开发语言·性能优化
用户47949283569155 小时前
面试官问 React Fiber,这一篇文章就够了
前端·javascript·react.js
小徐_23335 小时前
Gemini 3做粒子交互特效很出圈?拿 TRAE SOLO 来实现一波!
前端·ai编程·trae
LYFlied5 小时前
【一句话概述】Webpack、Vite、Rollup 核心区别
前端·webpack·node.js·rollup·vite·打包·一句话概述