你了解 Performance Timeline Level 2 吗?

什么是 Performance Timeline?

Performance Timeline是W3C性能小组提出的一个规范,定义了让开发者在应用整个生命周期内收集各类性能指标的接口。javascript

最新的Performance Timeline Level 2标准,取代了初版Performance Timeline标准,它包括了如下三点:html

  • 扩展了Performance接口的基本定义
  • 在Web Workers中暴露了PerformanceEntry
  • 增长了PerformanceObserver的支持

Performance Timeline 在 Node.js

值得注意的是,在Node.js里一样遵循W3C的Performance Timeline规范,实现了 Performance Hooks 接口。Performance Hooks 的API和现代浏览器中实现的 Performance API 是一致的。java

在浏览器中,咱们可使用 window 对象取得window.performancewindow.PerformanceObserver ,而在 Node.js 程序中须要 perf_hooks 取得性能对象,以下:node

const { PerformanceObserver, performance } = require('perf_hooks');
复制代码

浏览器兼容性

  • performance在浏览器中的兼容性
  • PerformanceObserver在浏览器中的兼容性
    PerformanceObserver兼容性

W3C性能小组鼓励开发人员在浏览器兼容性容许的状况下,尽量使用 PerformanceObserver。另外,新的性能API和指标可能只能经过PerformanceObserver 接口得到。json

performance 和 PerformanceObserver 的使用

window.performance

使用window.performance,咱们能够这样去度量某个函数的性能。api

function init() {
      performance.mark("startWork");
      doWork(); 
      performance.mark("endWork");
      performance.measure("work", "startWork", "endWork")
      measurePerf();
    }
    function measurePerf() {
      performance
        .getEntries()
        .map(entry => JSON.stringify(entry, null, 2))
        .forEach(json => console.log(json));
    }
复制代码

在上述代码中,咱们使用了performance.markperformance.measure来记录性能记录的数据。浏览器

performance.measure方法会根据 startMark 和 endMark 对应的,由 performance.mark产生的两条记录,来产生一条 entryType 为 'measure' 的新记录,并计算运行时长。bash

而后代码里使用了performance.getEntries来获取浏览器缓冲区中全部的性能数据记录。异步

固然,咱们也可使用performance.getEntriesByName获取指定 entryType 的性能记录。函数

window.PerformanceObserver

正如上文所述,咱们要想得到某项性能记录,须要知道指定的性能事件已经发生(或者使用定时轮训的方式),主动调用performance.getEntries或者performance.getEntriesByName来得到。

为了解决这个问题,在Performance Timeline Level 2中,除了扩展了Performance的基本定义之外,还增长了PerformanceObserver接口。

顾名思义,PerformanceObserver在浏览器内部对Performance实现了观察者模式,也是现代浏览器支持的几个 Observer 之一。

它解决了如下3点问题:

  • 避免不知道性能事件啥时候会发生,须要重复轮训timeline获取记录。
  • 避免产生重复的逻辑去获取不一样的性能数据指标
  • 避免其余资源须要操做浏览器性能缓冲区时产生竞态关系。

在兼容Performance Timeline Level 2的浏览器或者 Node.js 中,能够这样写:

const userTimingObserver = new PerformanceObserver(list => {
  list
    .getEntries()
    .map(({ name, entryType, startTime, duration }) => {
      const obj = {
        "Duration": duration,
        "Entry Type": entryType,
        "Name": name,
        "Start Time": startTime,
      };
      return JSON.stringify(obj, null, 2);
    })
    .forEach(console.log);
  userTimingObserver.disconnect();
});
userTimingObserver.observe({entryTypes: ["mark", "measure"]});
复制代码

另外有必要介绍一下 performanceObserver.observe 函数,它接受两个参数entryTypesbuffered

  • entryTypes 声明须要观察哪几类性能数据
  • buffered 声明回调函数是当即同步执行仍是异步执行,例子以下
const {
  performance,
  PerformanceObserver
} = require('perf_hooks');

const obs = new PerformanceObserver((list, observer) => {
  // 同步执行三次. 每次`list` 仅包含一项 item.
});
obs.observe({ entryTypes: ['mark'] });

for (let n = 0; n < 3; n++)
  performance.mark(`test${n}`);
复制代码
const {
  performance,
  PerformanceObserver
} = require('perf_hooks');

const obs = new PerformanceObserver((list, observer) => {
  // 执行一次. `list` 包含3个 items.
});
obs.observe({ entryTypes: ['mark'], buffered: true });

for (let n = 0; n < 3; n++)
  performance.mark(`test${n}`);
复制代码

总结

Performance Timeline Level 2规范中,扩充了performance的定义,并增长了PerformanceObserver的支持。

相比PerformanceObserverwindow.performance在浏览器中兼容性较好,另外Performance Hooks在 Node.js 中仍然处于 Experimental 阶段。

推荐在浏览器兼容的状况下使用PerformanceObserver,使用这种观察者模式能够解决主动调用的问题,并且更为优雅。

相关文章
相关标签/搜索