作者:basinwang,腾讯 PCG 前端开发工程师
大型项目容易遇到性能问题,一般来说,当我们遇到性能瓶颈的时候,才会开始去进行相应的分析。分析的方向除了业务本身的特点相关之外,常见的还可以借助一些工具来发现问题。本文主要介绍前端性能分析可以怎么走~
一般来说,前端的性能分析通常可以从时间和空间两个角度来进行:
那么,下面来看看有哪些常见的工具可以借来用用。由于我们的网页基本上跑在浏览器中,所以基本上大多数的工具都来源于浏览器自身提供,首选工具自然是 Chrome DevTools。本文我们也主要围绕 Chrome DevTools 来进行说明。
Lighthouse 的前身是 Chrome DevTools 面板中的 Audits。在 Chrome 60 之前的版本中, 这个面板只包含网络使用率和页面性能两个测量类别,从 Chrome 60 版本开始, Audits 面板已经被 Lighthouse 的集成版取代。而在最新版本的 Chrome 中,则需要单独安装 Lighthouse 拓展程序来使用,也可以通过脚本来使用。
Lighthouse 架构
下面是 Lighthouse 的组成部分:
Lighthouse 会在一系列的测试下运行网页,比如不同尺寸的设备和不同的网络速度。它还会检查页面对辅助功能指南的一致性,例如颜色对比度和 ARIA 最佳实践。
在比较短的时间内,Lighthouse 可以给出这样一份报告(可将报告生成为 JSON 或 html):
Lighthouse 架构
这份报告从 5 个方面来分析页面:性能、辅助功能、最佳实践、搜索引擎优化和 PWA。像性能方面,会给出一些常见的耗时统计。除此以外,还会给到一些详细的优化方向。
如果你希望短时间内对你的网站进行较全面的评估,可以使用 Lighthouse 来跑一下分数,确定大致的优化方向。
Performance 面板同样有个前身,叫 Timeline。该面板用于记录和分析运行时性能,运行时性能是页面运行时(而不是加载)的性能。
Performance 面板功能特别多,具体的分析也可以单独讲一篇了。这里我们简单说一下使用的步骤:
关于 Performance 怎么使用的文章特别多,大家网上随便搜一下就能搜到。一般来说,主要使用以下功能:
具体要怎么定位某些性能瓶颈,可以参考官方文档系列文章,这里就不详细介绍啦。
打开 Chrome 控制台后,按组合键ctrl + p(mac 快捷键为command + p),输入> Show Performance Monitor,就可以打开 Performance Monitor 性能监视器。主要的监控指标包括:
大多数情况下,我们在进行性能优化的时候,使用上面一些工具也足以确定大致的优化方向。更多的细节和案例,就不在这里详述了。
除了具体的性能分析和定位,我们也经常需要对业务进行性能监控。前端性能监控包括两种方式:合成监控(Synthetic Monitoring,SYN)、真实用户监控(Real User Monitoring,RUM)。
合成监控就是在一个模拟场景里,去提交一个需要做性能审计的页面,通过一系列的工具、规则去运行你的页面,提取一些性能指标,得出一个审计报告。例如上面介绍的 Lighthouse 就是合成监控。
合成监控的使用场景不多,一般可能出现在开发和测试的过程中,例如结合流水线跑性能报告、定位性能问题时本地跑的一些简单任务分析等。该方式的优点显而易见:
真实用户监控,就是用户在我们的页面上访问,访问之后就会产生各种各样的性能指标。我们在用户访问结束的时候,把这些性能指标上传到我们的日志服务器上,进行数据的提取清洗加工,最后在我们的监控平台上进行展示的一个过程。
我们提及前端监控的时候,大多数都包括了真实用户监控。常见的一些性能监控包括加载耗时、DOM 渲染耗时、接口耗时统计等,而对于页面加载过程,可以看到它被定义成了很多个阶段:
RUM 性能模型
而我们要做的,则是在力所能及的地方进行打点、计算、采集、上报,该过程常常需要借助 Performance Timeline API。将需要的数据发送到服务端,然后再对这些数据进行处理,最终通过可视化等方式进行监控。因此,真实用户监控往往需要结合业务本身的前后端架构设计来建设,其优点也比较容易理解:
对比合成监控,真实用户监控在有些场景下无法拿到更多的性能分析数据(例如具体哪里 CPU 占用、内存占用高),因此更多情况下作为优化效果来参考。这些情况下,具体的分析和定位可能还是得依赖合成监控。
但真实用户监控也有自身的优势,例如 TCP、DNS 连接耗时过高,在各种环境下的一些运行耗时问题,合成监控是很难发现的。
我们在开发过程中,也常常需要进行性能分析。而前端的性能分析上手成本也不低,除了基本的页面加载耗时、网络耗时,更具体的定位往往需要结合前面介绍的 Performance 面板、FPS、CPU、火焰图等一点点来分析。
如果这一块想要往自动化方向发展,我们可以怎么做呢?
前面也有介绍 Lighthouse,它提供了脚本的方式使用。因此,我们可以通过自动化任务跑脚本的方式,使用 Lighthouse 跑分析报告,通过对比以往的数据来进行功能变更、性能优化等场景的性能回归。
使用 Lighthouse 的优势在于开发成本低,只需要按照官方提供的配置来调整、获取自己需要的一些数据,就可以快速接入较全面的 Lighthouse 拥有的性能分析能力。
不过由于 Lighthouse 同样基于 CDP(Chrome DevTools Protocol),因此除了实现成本降低了,CDP 缺失的一些能力它也一样会缺失。
Chrome DevTools Protocol 允许第三方对基于 Chrome 的 Web 应用程序进行检测、检查、调试、分析等。有了这个协议,我们就可以自己开发工具获取 Chrome 的数据了。
Chrome DevTools 协议基于 WebSocket,利用 WebSocket 建立连接 DevTools 和浏览器内核的快速数据通道。
我们使用的 Chrome DevTools 其实也是一个 Web 应用。我们使用 DevTools 的时候,浏览器内核 Chromium 本身会作为一个服务端,我们看到的浏览器调试工具界面,通过 Websocket 和 Chromium 进行通信。建立过程如下:
同样的,当我们通过 DevTools 从 windows、Mac 或 linux 计算机远程调试 Android 设备上的实时内容时,使用的也是该协议。当 Chromium 以一个--remote-debugging-port=0标志启动时,它将启动 Chrome DevTools 协议服务器。
Chrome DevTools 协议具有与浏览器的许多不同部分(例如页面、Service Worker 和扩展程序)进行交互的 API。该协议把不同的操作划分为了不同的域(domain),每个域负责不同的功能模块。比如DOM、Debugger、Network、Console和Performance等,可以理解为 DevTools 中的不同功能模块。
使用该协议我们可以:
本文讲性能分析相关,因此这里我们只关注和性能相关的域。
1. Performance。从Performance域中Performance.getMetrics()可以拿到获取运行时性能指标包括:
2. Tracing。Tracing域可获取页面加载的 DevTools 性能跟踪。可以使用Tracing.start和Tracing.stop创建可在 Chrome DevTools 或时间轴查看器中打开的跟踪文件。
我们能看到生成的 JSON 文件长这样:
这样的 JSON 文件,我们可以丢到 DevTools Timeline Viewer 中,可以看到对应的时间轴和火焰图:
3. Runtime。Runtime域通过远程评估和镜像对象暴露 JavaScript 的运行时。可以通过Runtime.getHeapUsage获取 JavaScript 栈的使用情况,通过Runtime.evaluate计算全局对象的表达式,通过Runtime.queryObjects迭代 JavaScript 栈并查找具有给定原型的所有对象(可用于计算原型链中某处具有相同原型的所有对象,衡量 JavaScript 内存泄漏)。
除了上面介绍的这些,还有Network可以分析网络相关的性能,以及其他可能涉及 DOM 节点、JS 执行等各种各样的数据分析,更多的可能需要大家自己去研究了。
通过使用 Chrome DevTools 协议,我们可以获取 DevTools 提供的很多数据,包括网络数据、性能数据、运行时数据。
对于如何使用该协议,其实已经有很多大神针对这个协议封装出不同语言的库,包括 Node.js、Python、Java 等,可以根据需要在 awesome-chrome-devtools 这个项目中找到。
至于我们到底能拿到怎样的数据,可以做到怎样的自动化程度,就不在本文里讲述啦,后面有机会再开篇文章详细讲讲。
参考