12k
All articles

如何测量 JavaScript 性能

借助 DevTools、Performance API 和 Core Web Vitals 分析 JavaScript 执行,识别性能瓶颈并准确测量真实用户的 INP。

OpenReplay Team
OpenReplay Team
如何测量 JavaScript 性能

JavaScript 性能问题很容易感知,但很难精确定位。你的应用感觉迟缓,交互有延迟,用户会注意到——但如果没有合适的测量工具,你只能靠猜测。本文介绍使用现代浏览器 API 和 DevTools 进行实用的 JavaScript 性能测量技术,帮助你找到真正的瓶颈并修复正确的问题。

核心要点

  • 区分合成(实验室)测试和真实用户监控(RUM)——使用实验室工具进行诊断,使用现场数据进行验证。
  • Chrome DevTools 的 Performance 面板可显示长任务、火焰图和调用树,用于实际性能分析。
  • Performance API(performance.now()performance.mark()performance.measure())提供精确的程序化计时,可与 DevTools 集成。
  • PerformanceObserver 可自动收集条目用于生产环境监控,包括长任务检测。
  • Interaction to Next Paint(INP)是与响应性最密切相关的 Core Web Vital 指标。JavaScript 执行是主要影响因素,同时还包括样式、布局和绘制工作。

实验室测试 vs. 真实用户数据

在使用工具之前,需要了解 JavaScript 性能测量的两种类型:

  • 合成(实验室)测试在受控环境中运行你的代码。像 Lighthouse 和 Chrome DevTools 这样的工具可以提供可重复、可调试的结果。非常适合开发和 CI 流水线。
  • **现场数据(RUM)**捕获真实用户的体验。像 Chrome User Experience Report (CrUX) 或 RUM 平台这样的工具可以显示跨设备和网络的实际性能。

使用实验室工具诊断问题。使用现场数据确认问题的重要性。

在 Chrome DevTools 中分析 JavaScript

Chrome DevTools 是 JavaScript 性能指标测量最实用的起点。打开 Performance 面板,点击录制,与页面交互,然后停止。

需要关注的内容:

  • 长任务(Long Tasks)——任何阻塞主线程超过 50ms 的任务会以红色显示。这些通常会延迟用户交互。现代工具还可能显示长动画帧(Long Animation Frames),它提供影响响应性的慢帧的更详细信息。
  • 调用树/自底向上视图(Call Tree / Bottom-Up views)——识别哪些函数消耗了最多的执行时间。
  • 火焰图(Flame chart)——可视化随时间变化的调用堆栈,以发现昂贵的同步工作。

Firefox DevTools 提供类似的分析器。这两个工具都是免费的,无需设置,适用于任何网站。

使用 Performance API 测量 JavaScript 执行时间

对于精确的程序化 JavaScript 性能测量,使用浏览器内置的 Performance API

使用 performance.now()

performance.now() 返回以毫秒为单位的高分辨率时间戳,相对于页面的时间原点——这使其比 Date.now() 更可靠地用于代码计时。

const start = performance.now()
runExpensiveOperation()
const duration = performance.now() - start
console.log(`Took ${duration}ms`)

使用 performance.mark()performance.measure()

对于跨多个点的结构化计时,使用标记和测量。这可以直接与 DevTools 和 PerformanceObserver 集成。

performance.mark('fetch-start')
const data = await fetchData()
performance.mark('fetch-end')

const measure = performance.measure('fetch-duration', 'fetch-start', 'fetch-end')
console.log(measure.duration) // 毫秒

测量结果会出现在 Chrome DevTools Performance 面板的 Timings 轨道下,便于与主线程上的其他活动关联。

使用 PerformanceObserver 自动化测量

PerformanceObserver 允许你在性能条目发生时做出响应——对生产环境监控很有用。

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log(entry.name, entry.duration)
  }
})

observer.observe({ type: 'measure', buffered: true })

你还可以观察 longtask 条目,以检测真实用户会话中的主线程阻塞。

Core Web Vitals 和 INP:重要的指标

Google 的 Core Web Vitals 是用户体验的标准 JavaScript 性能指标。与 JavaScript 最相关的是 Interaction to Next Paint(INP)——它测量页面生命周期内所有交互(点击、轻触、键盘输入)的延迟。

INP 超过 200ms 是一个警告信号。超过 500ms 则表示性能较差。事件处理程序期间的大量 JavaScript 执行是最常见的原因。

使用 web-vitals 库在现场测量 INP:

import { onINP } from 'web-vitals'
onINP(({ value }) => console.log('INP:', value))

对于单页应用(SPA),请注意软导航(无需完整页面加载的路由更改)仅被标准导航指标部分捕获。浏览器对软导航测量的支持仍在发展中,因此使用 performance.mark() 手动检测路由转换可以帮助填补空白。

选择合适的工具

目标工具
快速调试console.time() / console.timeEnd()
精确计时performance.now()
结构化、可视化计时performance.mark() + performance.measure()
自动化监控PerformanceObserver
完整页面分析Chrome DevTools Performance 面板
审计评分 + 现场数据Lighthouse + CrUX

结论

有效的 JavaScript 性能测量始于为正确的问题选择合适的工具。使用 DevTools 进行分析和探索,使用 Performance API 检测特定代码路径,使用 Core Web Vitals——尤其是 INP——来了解用户的实际体验。先测量,再优化。

常见问题

在测量 JavaScript 执行时间时,performance.now() 和 Date.now() 有什么区别?

performance.now() 返回相对于页面时间原点的高分辨率时间戳,提供亚毫秒级精度。Date.now() 依赖系统时钟,可能受到时钟调整的影响,仅提供毫秒级分辨率。对于代码执行基准测试,performance.now() 是更准确和可靠的选择。

如何在生产环境中检测阻塞主线程的长任务?

使用配置为观察 longtask 类型条目的 PerformanceObserver。任何在主线程上超过 50ms 的任务都会被标记为长任务。通过在生产环境中收集这些条目,你可以识别哪些用户交互触发了阻塞工作,并优先优化最重要的部分。

什么是 INP,为什么它比 First Input Delay 更重要?

Interaction to Next Paint 测量页面访问期间所有交互的延迟,并报告最差的一次。First Input Delay 仅捕获第一次交互的延迟。INP 提供了运行时响应性的更全面的视图,这就是为什么 Google 在 2024 年 3 月用 INP 替换 FID 作为 Core Web Vital 的原因。

我可以使用 Performance API 测量像 fetch 请求这样的异步操作吗?

可以。在 await 表达式之前和之后放置 performance.mark() 调用,然后使用两个标记名称调用 performance.measure() 来计算经过的时间。生成的测量条目包括异步操作的完整持续时间,并出现在 DevTools Timings 轨道中以便进行可视化关联。

Open-source session replay

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.