On this page

稳定性:2 - 稳定

此模块提供了 W3C [Web Performance APIs][] 子集的实现,以及用于 Node.js 特定性能测量的其他 API。

Node.js 支持以下 [Web Performance APIs][]:

import { performance, PerformanceObserver } from 'node:perf_hooks';

const obs = new PerformanceObserver((items) => {
  console.log(items.getEntries()[0].duration);
  performance.clearMarks();
});
obs.observe({ type: 'measure' });
performance.measure('从开始到现在');

performance.mark('A');
doSomeLongRunningProcess(() => {
  performance.measure('A 到现在', 'A');

  performance.mark('B');
  performance.measure('A 到 B', 'A', 'B');
});

一个对象,可用于从当前 Node.js 实例收集性能指标。它类似于浏览器中的 window.performance

如果未提供 name,则从性能时间线中移除所有 PerformanceMark 对象。如果提供了 name,则仅移除命名的标记。

如果未提供 name,则从性能时间线中移除所有 PerformanceMeasure 对象。如果提供了 name,则仅移除命名的测量。

如果未提供 name,则从资源时间线中移除所有 PerformanceResourceTiming 对象。如果提供了 name,则仅移除命名的资源。

这是 perf_hooks.eventLoopUtilization() 的别名。

此属性是 Node.js 的扩展。它在 Web 浏览器中不可用。

返回按 performanceEntry.startTime 时间顺序排列的 PerformanceEntry 对象列表。如果你只关心特定类型或具有特定名称的性能条目,请参阅 performance.getEntriesByType()performance.getEntriesByName()

返回按 performanceEntry.startTime 时间顺序排列的 PerformanceEntry 对象列表,其 performanceEntry.name 等于 name,并且可选地,其 performanceEntry.entryType 等于 type

返回按 performanceEntry.startTime 时间顺序排列的 PerformanceEntry 对象列表,其 performanceEntry.entryType 等于 type

在性能时间线中创建一个新的 PerformanceMark 条目。PerformanceMarkPerformanceEntry 的子类,其 performanceEntry.entryType 始终为 'mark',且 performanceEntry.duration 始终为 0。性能标记用于标记性能时间线中的特定重要时刻。

创建的 PerformanceMark 条目被放入全局性能时间线中,可以通过 performance.getEntriesperformance.getEntriesByNameperformance.getEntriesByType 查询。当执行观察时,应使用 performance.clearMarks 手动从全局性能时间线中清除条目。

此属性是 Node.js 的扩展。它在 Web 浏览器中不可用。

在资源时间线中创建一个新的 PerformanceResourceTiming 条目。PerformanceResourceTimingPerformanceEntry 的子类,其 performanceEntry.entryType 始终为 'resource'。性能资源用于标记资源时间线中的时刻。

创建的 PerformanceMark 条目被放入全局资源时间线中,可以通过 performance.getEntriesperformance.getEntriesByNameperformance.getEntriesByType 查询。当执行观察时,应使用 performance.clearResourceTimings 手动从全局性能时间线中清除条目。

在性能时间线中创建一个新的 PerformanceMeasure 条目。PerformanceMeasurePerformanceEntry 的子类,其 performanceEntry.entryType 始终为 'measure',且 performanceEntry.duration 测量自 startMarkendMark 以来经过的毫秒数。

startMark 参数可以标识性能时间线中的任何 现有 PerformanceMark,或者 可以 标识 PerformanceNodeTiming 类提供的任何时间戳属性。如果命名的 startMark 不存在,则会抛出错误。

可选的 endMark 参数必须标识性能时间线中的任何 现有 PerformanceMarkPerformanceNodeTiming 类提供的任何时间戳属性。如果没有传递参数,endMark 将为 performance.now(),否则如果命名的 endMark 不存在,将抛出错误。

创建的 PerformanceMeasure 条目被放入全局性能时间线中,可以通过 performance.getEntriesperformance.getEntriesByNameperformance.getEntriesByType 查询。当执行观察时,应使用 performance.clearMeasures 手动从全局性能时间线中清除条目。

此属性是 Node.js 的扩展。它在 Web 浏览器中不可用。

PerformanceNodeTiming 类的一个实例,为特定的 Node.js 操作里程碑提供性能指标。

返回当前高分辨率毫秒时间戳,其中 0 代表当前 node 进程的开始。

默认情况下,最大缓冲区大小设置为 250。

timeOrigin 指定当前 node 进程开始的高分辨率毫秒时间戳,以 Unix 时间测量。

这是 perf_hooks.timerify() 的别名。

此属性是 Node.js 的扩展。它在 Web 浏览器中不可用。

当全局性能资源时间线缓冲区已满时,会触发 'resourcetimingbufferfull' 事件。在事件监听器中使用 performance.setResourceTimingBufferSize() 调整资源时间线缓冲区大小,或使用 performance.clearResourceTimings() 清除缓冲区,以允许更多条目添加到性能时间线缓冲区中。

此类的构造函数不直接向用户暴露。

该条目经过的总毫秒数。此值并不适用于所有性能条目类型。

性能条目的类型。它可能是以下之一:

  • 'dns'(仅 Node.js)
  • 'function'(仅 Node.js)
  • 'gc'(仅 Node.js)
  • 'http2'(仅 Node.js)
  • 'http'(仅 Node.js)
  • 'mark'(Web 上可用)
  • 'measure'(Web 上可用)
  • 'net'(仅 Node.js)
  • 'node'(仅 Node.js)
  • 'resource'(Web 上可用)

性能条目的名称。

标记性能条目开始时间的高分辨率毫秒时间戳。

暴露通过 Performance.mark() 方法创建的标记。

使用 Performance.mark() 方法创建时指定的附加详情。

暴露通过 Performance.measure() 方法创建的测量。

此类的构造函数不直接暴露给用户。

使用 Performance.measure() 方法创建时指定的附加详情。

此类是 Node.js 的扩展。它在 Web 浏览器中不可用。

提供详细的 Node.js 计时数据。

此类的构造函数不直接暴露给用户。

特定于 entryType 的附加详情。

performanceEntry.entryType 等于 'gc' 时,performance.flags 属性包含有关垃圾回收操作的附加信息。该值可能是以下之一:

  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_NO
  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED
  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_FORCED
  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING
  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE
  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY
  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE

performanceEntry.entryType 等于 'gc' 时,performance.kind 属性标识发生的垃圾回收操作类型。该值可能是以下之一:

  • perf_hooks.constants.NODE_PERFORMANCE_GC_MAJOR
  • perf_hooks.constants.NODE_PERFORMANCE_GC_MINOR
  • perf_hooks.constants.NODE_PERFORMANCE_GC_MINOR_MARK_SWEEP
  • perf_hooks.constants.NODE_PERFORMANCE_GC_INCREMENTAL
  • perf_hooks.constants.NODE_PERFORMANCE_GC_WEAKCB
Attributes
以下之一:
perf_hooks.constants.NODE_PERFORMANCE_GC_MAJOR:
perf_hooks.constants.NODE_PERFORMANCE_GC_MINOR:
perf_hooks.constants.NODE_PERFORMANCE_GC_MINOR_MARK_SWEEP:
perf_hooks.constants.NODE_PERFORMANCE_GC_INCREMENTAL:
perf_hooks.constants.NODE_PERFORMANCE_GC_WEAKCB:
flags:<number>
以下之一:
perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_NO:
perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED:
perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_FORCED:
perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING:
perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE:
perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY:
perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE:

如果 performanceEntry.name 等于 HttpClientdetail 将包含以下属性:req, resreq 属性将是一个包含 method, url, headers 的 <Object>res 属性将是一个包含 statusCode, statusMessage, headers 的 <Object>

如果 performanceEntry.name 等于 HttpRequestdetail 将包含以下属性:req, resreq 属性将是一个包含 method, url, headers 的 <Object>res 属性将是一个包含 statusCode, statusMessage, headers 的 <Object>

这可能会增加额外的内存开销,应仅用于诊断目的,默认情况下不应在生产环境中保持开启。

如果 performanceEntry.name 等于 Http2Streamdetail 将包含以下属性:

Attributes
bytesRead:<number>
为此  Http2Stream 接收的 DATA 帧字节数。
bytesWritten:<number>
为此  Http2Stream 发送的 DATA 帧字节数。
关联  Http2Stream 的标识符。
timeToFirstByte:<number>
PerformanceEntry startTime 与接收第一个 DATA 帧之间经过的毫秒数。
timeToFirstByteSent:<number>
PerformanceEntry startTime 与发送第一个 DATA 帧之间经过的毫秒数。
timeToFirstHeader:<number>
PerformanceEntry startTime 与接收第一个头之间经过的毫秒数。

如果 performanceEntry.name 等于 Http2Sessiondetail 将包含以下属性:

Attributes
bytesRead:<number>
为此  Http2Session 接收的字节数。
bytesWritten:<number>
为此  Http2Session 发送的字节数。
framesReceived:<number>
Http2Session 接收的 HTTP/2 帧数。
framesSent:<number>
Http2Session 发送的 HTTP/2 帧数。
maxConcurrentStreams:<number>
Http2Session 生命周期内同时打开的最大流数。
pingRTT:<number>
自发送  PING 帧到接收其确认之间经过的毫秒数。仅在 Http2Session 上发送了 PING 帧时存在。
streamAverageDuration:<number>
所有  Http2Stream 实例的平均持续时间(毫秒)。
streamCount:<number>
Http2Session 处理的 Http2Stream 实例数。
'server''client' ,用于标识 Http2Session 的类型。

如果 performanceEntry.name 等于 connectdetail 将包含以下属性:host, port

如果 performanceEntry.name 等于 lookupdetail 将包含以下属性:hostname, family, hints, verbatim, addresses

如果 performanceEntry.name 等于 lookupServicedetail 将包含以下属性:host, port, hostname, service

如果 performanceEntry.name 等于 queryxxxgetHostByAddrdetail 将包含以下属性:host, ttl, resultresult 的值与 queryxxxgetHostByAddr 的结果相同。

此属性是 Node.js 的扩展。它在 Web 浏览器中不可用。

提供 Node.js 本身的计时详情。此类的构造函数不向用户暴露。

Node.js 进程完成引导的高分辨率毫秒时间戳。如果引导尚未完成,则该属性的值为 -1。

Node.js 环境初始化的高分辨率毫秒时间戳。

事件循环在其事件提供者(例如 epoll_wait)内处于空闲状态的时间量的高分辨率毫秒时间戳。这不考虑 CPU 使用情况。如果事件循环尚未启动(例如,在主脚本的第一个刻度中),则该属性的值为 0。

Node.js 事件循环退出时的高分辨率毫秒时间戳。如果事件循环尚未退出,则该属性的值为 -1。它只能在 'exit' 事件的处理程序中具有非 -1 的值。

Node.js 事件循环启动时的高分辨率毫秒时间戳。如果事件循环尚未启动(例如,在主脚本的第一个刻度中),则该属性的值为 -1。

Node.js 进程初始化时的高分辨率毫秒时间戳。

这是 uv_metrics_info 函数的包装器。 它返回当前的一组事件循环指标。

建议在通过 setImmediate 调度执行的函数内部使用此属性,以避免在当前循环迭代期间计划的所有操作完成之前收集指标。

const { performance } = require('node:perf_hooks');

setImmediate(() => {
  console.log(performance.nodeTiming.uvMetricsInfo);
});

V8 平台初始化时的高分辨率毫秒时间戳。

提供有关应用程序资源加载的详细网络计时数据。

此类的构造函数不直接暴露给用户。

调度 fetch 请求之前立即的高分辨率毫秒时间戳。如果资源未被工作器拦截,则该属性将始终返回 0。

表示发起重定向的 fetch 开始时间的高分辨率毫秒时间戳。

接收到最后一个重定向响应的最后一个字节后立即创建的高分辨率毫秒时间戳。

Node.js 开始获取资源之前立即的高分辨率毫秒时间戳。

Node.js 开始资源的域名查找之前立即的高分辨率毫秒时间戳。

表示 Node.js 完成资源的域名查找之后立即的时间的高分辨率毫秒时间戳。

表示 Node.js 开始建立与服务器的连接以检索资源之前立即的时间的高分辨率毫秒时间戳。

表示 Node.js 完成建立与服务器的连接以检索资源之后立即的时间的高分辨率毫秒时间戳。

表示 Node.js 开始握手过程以保护当前连接之前立即的时间的高分辨率毫秒时间戳。

表示 Node.js 接收到来自服务器的响应的第一个字节之前立即的时间的高分辨率毫秒时间戳。

表示 Node.js 接收到资源的最后一个字节之后立即或传输连接关闭之前立即的时间的高分辨率毫秒时间戳,以先发生者为准。

一个数字,表示获取的资源的大小(以八位字节为单位)。大小包括响应头字段加上响应负载主体。

一个数字,表示从 fetch(HTTP 或缓存)接收的负载主体的大小(以八位字节为单位),在移除任何应用的内容编码之前。

一个数字,表示从 fetch(HTTP 或缓存)接收的消息主体的大小(以八位字节为单位),在移除任何应用的内容编码之后。

获取支持的类型。

PerformanceObserver 对象在新的 PerformanceEntry 实例被添加到性能时间轴时提供通知。

import { performance, PerformanceObserver } from 'node:perf_hooks';

const obs = new PerformanceObserver((list, observer) => {
  console.log(list.getEntries());

  performance.clearMarks();
  performance.clearMeasures();
  observer.disconnect();
});
obs.observe({ entryTypes: ['mark'], buffered: true });

performance.mark('test');

因为 PerformanceObserver 实例引入了它们自己额外的性能开销,实例不应无限期地订阅通知。用户应在不再需要观察者时尽快断开连接。

PerformanceObserver 收到新的 PerformanceEntry 实例通知时,会调用 callback。回调接收一个 PerformanceObserverEntryList 实例和对 PerformanceObserver 的引用。

订阅 <PerformanceObserver> 实例以接收新的 <PerformanceEntry> 实例的通知,这些实例由 options.entryTypesoptions.type 标识:

import { performance, PerformanceObserver } from 'node:perf_hooks';

const obs = new PerformanceObserver((list, observer) => {
  // 异步调用一次。`list` 包含三个项。
});
obs.observe({ type: 'mark' });

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

PerformanceObserverEntryList 类用于提供对传递给 PerformanceObserverPerformanceEntry 实例的访问。 此类的构造函数不对用户暴露。

返回一个 PerformanceEntry 对象列表,按照 performanceEntry.startTime 的时间顺序排列。

import { performance, PerformanceObserver } from 'node:perf_hooks';

const obs = new PerformanceObserver((perfObserverList, observer) => {
  console.log(perfObserverList.getEntries());
  /**
   * [
   *   PerformanceEntry {
   *     name: 'test',
   *     entryType: 'mark',
   *     startTime: 81.465639,
   *     duration: 0,
   *     detail: null
   *   },
   *   PerformanceEntry {
   *     name: 'meow',
   *     entryType: 'mark',
   *     startTime: 81.860064,
   *     duration: 0,
   *     detail: null
   *   }
   * ]
   */

  performance.clearMarks();
  performance.clearMeasures();
  observer.disconnect();
});
obs.observe({ type: 'mark' });

performance.mark('test');
performance.mark('meow');

返回一个 PerformanceEntry 对象列表,按照 performanceEntry.startTime 的时间顺序排列,其 performanceEntry.name 等于 name,并且可选地,其 performanceEntry.entryType 等于 type

import { performance, PerformanceObserver } from 'node:perf_hooks';

const obs = new PerformanceObserver((perfObserverList, observer) => {
  console.log(perfObserverList.getEntriesByName('meow'));
  /**
   * [
   *   PerformanceEntry {
   *     name: 'meow',
   *     entryType: 'mark',
   *     startTime: 98.545991,
   *     duration: 0,
   *     detail: null
   *   }
   * ]
   */
  console.log(perfObserverList.getEntriesByName('nope')); // []

  console.log(perfObserverList.getEntriesByName('test', 'mark'));
  /**
   * [
   *   PerformanceEntry {
   *     name: 'test',
   *     entryType: 'mark',
   *     startTime: 63.518931,
   *     duration: 0,
   *     detail: null
   *   }
   * ]
   */
  console.log(perfObserverList.getEntriesByName('test', 'measure')); // []

  performance.clearMarks();
  performance.clearMeasures();
  observer.disconnect();
});
obs.observe({ entryTypes: ['mark', 'measure'] });

performance.mark('test');
performance.mark('meow');

返回一个 PerformanceEntry 对象列表,按照 performanceEntry.startTime 的时间顺序排列,其 performanceEntry.entryType 等于 type

import { performance, PerformanceObserver } from 'node:perf_hooks';

const obs = new PerformanceObserver((perfObserverList, observer) => {
  console.log(perfObserverList.getEntriesByType('mark'));
  /**
   * [
   *   PerformanceEntry {
   *     name: 'test',
   *     entryType: 'mark',
   *     startTime: 55.897834,
   *     duration: 0,
   *     detail: null
   *   },
   *   PerformanceEntry {
   *     name: 'meow',
   *     entryType: 'mark',
   *     startTime: 56.350146,
   *     duration: 0,
   *     detail: null
   *   }
   * ]
   */
  performance.clearMarks();
  performance.clearMeasures();
  observer.disconnect();
});
obs.observe({ type: 'mark' });

performance.mark('test');
performance.mark('meow');
Attributes
options:<Object>
最低可分辨值。必须是大于 0 的整数值。 默认值: 1
highest:<number> | <bigint>
最高可记录值。必须是等于或大于  lowest 两倍的整数值。 默认值: Number.MAX_SAFE_INTEGER
figures:<number>
精度位数。必须是  15 之间的数字。 默认值: 3

返回一个 <RecordableHistogram>

Attributes
utilization1:<Object>
之前调用  eventLoopUtilization() 的结果。
utilization2:<Object>
在  utilization1 之前调用 eventLoopUtilization() 的结果。
active:<number>
utilization:<number>

eventLoopUtilization() 函数返回一个对象,该对象包含事件循环处于空闲和活动状态的累计持续时间,作为高分辨率毫秒计时器。utilization 值是计算出的事件循环利用率 (ELU)。

如果主线程上的引导尚未完成,则属性的值为 0。由于引导发生在事件循环内,因此 ELU 在 工作线程 上立即可用。

utilization1utilization2 都是可选参数。

如果传入了 utilization1,则会计算并返回当前调用的 activeidle 时间之间的差值,以及相应的 utilization 值(类似于 process.hrtime())。

如果同时传入了 utilization1utilization2,则会计算这两个参数之间的差值。这是一个便利选项,因为与 process.hrtime() 不同,计算 ELU 比单次减法更复杂。

ELU 类似于 CPU 利用率,但它仅测量事件循环统计信息,而不是 CPU 使用情况。它表示事件循环花在事件循环的事件提供者(例如 epoll_wait)之外的时间百分比。不考虑其他 CPU 空闲时间。以下是一个大部分空闲的进程如何具有高 ELU 的示例。

import { eventLoopUtilization } from 'node:perf_hooks';
import { spawnSync } from 'node:child_process';

setImmediate(() => {
  const elu = eventLoopUtilization();
  spawnSync('sleep', ['5']);
  console.log(eventLoopUtilization(elu).utilization);
});

虽然运行此脚本时 CPU 大部分处于空闲状态,但 utilization 的值为 1。这是因为对 child_process.spawnSync() 的调用阻止了事件循环继续执行。

传入用户定义的对象而不是之前调用 eventLoopUtilization() 的结果会导致未定义的行为。返回值不保证反映事件循环的任何正确状态。

Attributes
options:<Object>
samplePerIteration:<boolean>
当为  true 时,样本会在每次 事件循环迭代时采集一次。 默认值: false
resolution:<number>
基于间隔采样时,以毫秒为单位的采样频率。 必须大于零。当前选项为  samplePerIteration 时会忽略此选项。 默认值: 10

此属性是 Node.js 的扩展。它在 Web 浏览器中不可用。

创建一个直方图对象,用于随时间采样并报告事件循环延迟。 延迟将以纳秒为单位报告。

默认情况下,直方图会通过使用已配置的 resolution 的计时器进行更新。 当 samplePerIterationtrue 时,样本会使用 uv_prepare_tuv_check_t 钩子在每次事件循环迭代时采集一次。 在该模式下,直方图不会保持事件循环存活,也不会在应用空闲时强制额外迭代。 这两种采样模式产生的结果差异很大,不应直接比较。

import { monitorEventLoopDelay } from 'node:perf_hooks';

const h = monitorEventLoopDelay({ resolution: 20 });
h.enable();
// 做一些事情。
h.disable();
console.log(h.min);
console.log(h.max);
console.log(h.mean);
console.log(h.stddev);
console.log(h.percentiles);
console.log(h.percentile(50));
console.log(h.percentile(99));
Attributes
options:<Object>
A histogram object created using  perf_hooks.createHistogram() , used to record runtime durations in nanoseconds.

This property is an extension of Node.js. It is not available in Web browsers.

Wraps the function in a new function that measures the wrapped function’s runtime. A PerformanceObserver must be subscribed to the 'function' entry type to access the timing details.

import { timerify, performance, PerformanceObserver } from 'node:perf_hooks';

function someFunction() {
  console.log('hello world');
}

const wrapped = timerify(someFunction);

const obs = new PerformanceObserver((list) => {
  console.log(list.getEntries()[0].duration);

  performance.clearMarks();
  performance.clearMeasures();
  obs.disconnect();
});
obs.observe({ entryTypes: ['function'] });

// A performance timeline entry will be created
wrapped();

If the wrapped function returns a promise, a finally handler will be attached to the promise and the duration will be reported once the finally handler is invoked.

直方图记录的样本数。

直方图记录的样本数。

事件循环延迟超过最大 1 小时事件循环延迟阈值的次数。

事件循环延迟超过最大 1 小时事件循环延迟阈值的次数。

记录的最大事件循环延迟。

记录的最大事件循环延迟。

记录的事件循环延迟平均值。

记录的最小事件循环延迟。

记录的最小事件循环延迟。

返回给定百分位处的值。

返回给定百分位处的值。

返回一个 Map 对象,详细说明累积的百分位分布。

返回一个 Map 对象,详细说明累积的百分位分布。

记录的事件循环延迟标准差。

一种记录事件循环延迟的 Histogram,由 perf_hooks.monitorEventLoopDelay() 返回。

禁用事件循环延迟采样。如果采样已停止,则返回 true;如果它本来就已停止,则返回 false

启用事件循环延迟采样。如果采样已启动,则返回 true;如果它本来就已启动,则返回 false

const { monitorEventLoopDelay } = require('node:perf_hooks');
{
  using hist = monitorEventLoopDelay({ resolution: 20 });
  hist.enable();
  // 当退出块时,直方图将被禁用。
}

other 中的值添加到此直方图。

import { createHook } from 'node:async_hooks';
import { performance, PerformanceObserver } from 'node:perf_hooks';

const set = new Set();
const hook = createHook({
  init(id, type) {
    if (type === 'Timeout') {
      performance.mark(`Timeout-${id}-Init`);
      set.add(id);
    }
  },
  destroy(id) {
    if (set.has(id)) {
      set.delete(id);
      performance.mark(`Timeout-${id}-Destroy`);
      performance.measure(`Timeout-${id}`,
                          `Timeout-${id}-Init`,
                          `Timeout-${id}-Destroy`);
    }
  },
});
hook.enable();

const obs = new PerformanceObserver((list, observer) => {
  console.log(list.getEntries()[0]);
  performance.clearMarks();
  performance.clearMeasures();
  observer.disconnect();
});
obs.observe({ entryTypes: ['measure'], buffered: true });

setTimeout(() => {}, 1000);