性能数据
Performance API 测量并公开可为您的 Web 应用程序收集的性能指标。它提供了观察应用程序性能各个方面的方法。它不提供性能数据分析或可视化。然而,Performance API 与浏览器中的开发者工具集成良好,其数据通常会发送到分析端点和库,以记录有助于您评估数据以找出影响用户性能瓶颈的性能指标。
本页面提供了关于存在哪些 Performance API 数据、如何收集这些数据以及如何访问这些数据的概述。
收集数据
Performance API 公开的大多数指标都会由浏览器自动收集,您无需告诉它去收集:只需检索即可。
某些指标确实需要您告诉浏览器要测量什么
Element Timing指标测量加载和渲染特定 DOM 元素所需的时间。此指标需要选择加入:要要求浏览器包含特定元素的指标,您必须为其添加elementtiming属性。User Timing指标使您能够测量程序中任意两点之间的时间,这些点可能对应于应用程序定义的事务(例如用户登录)。要收集这些指标,您需要在相关点添加 Performance API 调用。Server Timing指标使您能够测量应用程序定义的服务器端事务所需的时间。要收集这些指标,您的服务器必须发送Server-TimingHTTP 标头。
性能数据结构
使用 Performance API,您可以在 Window 和 Worker 的全局上下文中收集性能数据。如果您正在为多个上下文收集性能指标,请查看 performance.timeOrigin 以同步不同上下文的时间起点。
在这些上下文中,单个性能数据由性能条目表示。
性能条目
单个记录的性能数据点称为*性能条目*,它由 PerformanceEntry 接口的实例表示。
Performance API 记录各种不同类型的性能数据,而 PerformanceEntry 有一个 entryType 属性,它是一个描述此性能条目类型的字符串
"element"记录元素加载和渲染所需的时间。"event"记录浏览器响应事件触发器开始运行事件处理程序所需的时间,以及事件处理程序运行所需的时间。用于测量 下次绘制交互。"first-input"记录 首次输入延迟。"largest-contentful-paint"记录页面加载期间最大的绘制。"layout-shift"记录每个动画帧中页面布局移动了多少的度量。"longtask"记录耗时 50 毫秒或更长的任务。"mark"记录开发者创建的自定义时间戳。"measure"记录开发者创建的两个时间戳之间的自定义测量。"navigation"记录与导航到页面和页面初始加载相关的指标。"paint"记录页面加载期间渲染的关键时刻。"resource"记录浏览器获取资源所需的时间。"visibility-state"记录页面可见状态更改的时间,即选项卡从前台切换到后台或反之亦然。
性能条目子类
特定的条目类型通常包含额外的特定类型数据:例如,"resource" 类型捕获 DNS 查找开始和结束的时间。因此,条目由扩展基本 PerformanceEntry 接口的子类表示。例如,"resource" 条目由 PerformanceResourceTiming 接口的实例表示,该接口继承自 PerformanceEntry,并添加了用于记录 DNS 查找时间戳的属性。
PerformanceEntry 的子类也定义了 PerformanceEntry 本身属性的语义:例如,PerformanceEntry 有一个 name 属性,其含义取决于子类。
以下接口继承自 PerformanceEntry
访问数据
您可以通过两种方式访问性能条目。首选方式是使用 PerformanceObserver 接口,该接口使用一个回调函数进行构造,当记录特定性能条目时调用该函数。然后调用其 observe 方法,传入要观察的类型,并使用 buffered 选项来检索在观察之前发生的条目。
function logEventDuration(entries) {
const events = entries.getEntriesByType("event");
for (const event of events) {
console.log(
`Event handler took: ${
event.processingEnd - event.processingStart
} milliseconds`,
);
}
}
const observer = new PerformanceObserver(logEventDuration);
observer.observe({ type: "event", buffered: true });
或者,您可以使用 Performance.getEntries()、Performance.getEntriesByName() 和 Performance.getEntriesByType() 方法来检索页面上的所有性能条目,或者检索与给定名称或类型匹配的条目。
const events = performance.getEntriesByType("event");
for (const event of events) {
console.log(
`Event handler took: ${
event.processingEnd - event.processingStart
} milliseconds`,
);
}
PerformanceObserver 选项更受青睐,因为
getEntries*方法将始终返回自时间轴开始以来所有相关的条目,因此如果您调用它两次,您将再次看到相同的条目,并且需要过滤掉您之前看到的条目。- 观察者通知是异步传递的,因此浏览器可以在空闲时间分派它们,以最大限度地减少其性能影响。
- 并非所有条目类型都与
getEntries*方法一起使用。对于某些条目,您必须使用性能观察者来访问它们。
管理缓冲区大小
每个全局对象都有一个性能条目的缓冲区限制。它确保浏览器在持有性能数据时不会消耗无限内存。特别是当您的网站或应用程序获取大量资源时(例如,在使用轮询时),您可能需要查看缓冲区的限制。
entryType 标识符 |
接口 | 最大缓冲区条目数 |
|---|---|---|
"mark" |
PerformanceMark |
无限 |
"measure" |
PerformanceMeasure |
无限 |
"navigation" |
PerformanceNavigationTiming |
无限 |
"resource" |
PerformanceResourceTiming |
250(可调,见下文) |
"longtask" |
PerformanceLongTaskTiming |
200 |
"paint" |
PerformancePaintTiming |
2(不会更多) |
"element" |
PerformanceElementTiming |
150 |
"event" |
PerformanceEventTiming |
150 |
"first-input" |
PerformanceEventTiming |
1(不会更多) |
"layout-shift" |
LayoutShift |
150 |
"largest-contentful-paint" |
LargestContentfulPaint |
150 |
"visibility-state" |
VisibilityStateEntry |
50 |
表 1. 缓冲区大小(来源)。
对于 "resource" 条目类型,请参阅 管理资源缓冲区大小,了解如何设置不同的缓冲区大小。
对于 "first-input" 和 "paint",限制是指标定义固有的。条目不会超过一个(或两个)。
PerformanceObserver 的回调函数包含一个可选的 droppedEntriesCount 参数,它告诉您由于缓冲区存储已满而丢失了多少条目。
function perfObserver(list, observer, droppedEntriesCount) {
list.getEntries().forEach((entry) => {
// do something with the entries
});
if (droppedEntriesCount > 0) {
console.warn(
`${droppedEntriesCount} entries were dropped because the buffer was full.`,
);
}
}
const observer = new PerformanceObserver(perfObserver);
observer.observe({ type: "resource", buffered: true });
另一个有用的方法是 PerformanceObserver.takeRecords(),它返回性能观察者中存储的性能条目列表,同时清空它。
JSON 数据
所有性能条目都提供了一个 toJSON() 序列化器,它返回条目的 JSON 表示形式。如果您想收集所有可用数据并将其存储在某处,这会很有用。
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
console.log(entry.toJSON());
});
});
observer.observe({ type: "event", buffered: true });
这将记录一个类似如下的 JSON 对象
{
"name": "dragover",
"entryType": "event",
"startTime": 67090751.599999905,
"duration": 128,
"processingStart": 67090751.70000005,
"processingEnd": 67090751.900000095,
"cancelable": true
}
要获取条目的字符串表示形式,您可以直接对任何 PerformanceEntry 对象使用 JSON.stringify(entry);它会自动调用条目的 toJSON() 方法。