借助渐进式 Web 应用,开发者可以构建一类全新的应用,从而提供可靠且高性能的用户体验。不过,为了确保 Web 应用能够实现预期的性能目标,开发者需要访问高分辨率的性能衡量数据。W3C 性能时间轴规范定义了这样一个接口,以便浏览器以编程方式访问低级时间数据。这为一些有趣的用例打开了大门:
- 离线和自定义效果分析
- 第三方性能分析和可视化工具
- 集成到 IDE 和其他开发者工具中的性能评估
大多数主要浏览器都已支持访问此类时间数据,以便获取导航时间、资源时间和用户时间。最新添加的是性能观察器接口,它本质上是一种流式接口,用于异步收集由浏览器收集的低级时间信息。与之前访问时间轴的方法相比,此新界面具有多项关键优势:
- 目前,应用必须定期轮询存储的测量结果并进行差异化处理,这会产生高昂的开销。此接口会为它们提供回调。(也就是说,无需轮询)。因此,使用此 API 的应用可以提高响应速度并提升效率。
- 它不受缓冲区限制(大多数缓冲区默认设置为 150 个项),并避免了可能想要修改缓冲区的不同使用方之间出现竞态条件。
- 性能观察器通知是异步传送的,浏览器可以在空闲时间调度这些通知,以免与关键渲染工作争用资源。
从 Chrome 52 开始,性能观察器接口默认处于启用状态。我们来看看该工具的使用方式。
<html>
<head>
<script>
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => {
// Display each reported measurement on console
if (console) {
console.log("Name: " + entry.name +
", Type: " + entry.entryType +
", Start: " + entry.startTime +
", Duration: " + entry.duration + "\n");
}
})
});
observer.observe({entryTypes: ['resource', 'mark', 'measure']});
performance.mark('registered-observer');
function clicked(elem) {
performance.measure('button clicked');
}
</script>
</head>
<body>
<button onclick="clicked(this)">Measure</button>
</body>
</html>
此简单页面以一个脚本标记开头,该标记定义了一些 JavaScript 代码:
- 我们实例化一个新的
PerformanceObserver
对象,并将事件处理程序函数传递给对象构造函数。构造函数会初始化对象,以便在每次有新一组衡量数据准备好处理时(将衡量数据作为对象列表传递),系统都会调用我们的处理脚本。此处将处理程序定义为一个匿名函数,该函数只会在控制台中显示格式化的测量数据。在实际场景中,这些数据可能会存储在云端以供后续分析,或管道传输到交互式可视化工具。 - 我们通过
observe()
方法注册感兴趣的类型的时间事件,并调用mark()
方法来标记注册时刻,我们将其视为时间间隔的开始。 - 我们为页面正文中定义的按钮定义了一个点击处理脚本。此点击处理脚本会调用
measure()
方法,以捕获有关点击按钮时间的数据。
在页面正文中,我们定义一个按钮,将点击处理脚本分配给 onclick
事件,然后就可以开始了。
现在,如果我们加载该页面并打开 Chrome DevTools 面板以监控 JavaScript 控制台,那么每次点击该按钮都会进行性能测量。由于我们已注册以观察此类测量,因此系统会异步将这些测量结果转发给事件处理脚本,而无需轮询时间轴,后者会在测量结果发生时在控制台中显示这些测量结果:
start
值表示类型为 mark
的事件的开始时间戳(此应用只有一个此类事件)。类型为 measure
的事件没有固有的开始时间;它们表示相对于上一个 mark
事件所测量的时间。因此,此处显示的时长值表示对 mark()
的调用(作为常规间隔的起始点)与对 measure()
的多次后续调用之间的经过时间。
如您所见,此 API 非常简单,能够在不轮询的情况下收集经过过滤的高分辨率实时性能数据,这应该为 Web 应用提供了更高效的性能工具。