性能测量 API#

稳定性:2 - 稳定

源代码: lib/perf_hooks.js

此模块提供了 W3C Web 性能 API 的一个子集的实现,以及用于 Node.js 特定性能测量的额外 API。

Node.js 支持以下 Web 性能 API

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('Start to Now');

performance.mark('A');
doSomeLongRunningProcess(() => {
  performance.measure('A to Now', 'A');

  performance.mark('B');
  performance.measure('A to B', 'A', 'B');
});const { PerformanceObserver, performance } = require('node:perf_hooks');

const obs = new PerformanceObserver((items) => {
  console.log(items.getEntries()[0].duration);
});
obs.observe({ type: 'measure' });
performance.measure('Start to Now');

performance.mark('A');
(async function doSomeLongRunningProcess() {
  await new Promise((r) => setTimeout(r, 5000));
  performance.measure('A to Now', 'A');

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

perf_hooks.performance#

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

performance.clearMarks([name])#

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

performance.clearMeasures([name])#

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

performance.clearResourceTimings([name])#

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

performance.eventLoopUtilization([utilization1[, utilization2]])#

eventLoopUtilization() 方法返回一个对象,该对象包含事件循环处于空闲和活动状态的累积持续时间,以高精度毫秒计时器表示。utilization 值是计算出的事件循环利用率 (ELU)。

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

utilization1utilization2 都是可选参数。

如果传入了 utilization1,则会计算并返回当前调用与 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);
});'use strict';
const { eventLoopUtilization } = require('node:perf_hooks').performance;
const { spawnSync } = require('node:child_process');

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

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

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

performance.getEntries()#

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

performance.getEntriesByName(name[, type])#

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

performance.getEntriesByType(type)#

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

performance.mark(name[, options])#

  • name <string>
  • options <Object>
    • detail <any> 附加到标记的可选详细信息。
    • startTime <number> 用作标记时间的可选时间戳。默认值performance.now()

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

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

performance.markResourceTiming(timingInfo, requestedUrl, initiatorType, global, cacheMode, bodyInfo, responseStatus[, deliveryType])#

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

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

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

performance.measure(name[, startMarkOrOptions[, endMark]])#

  • name <string>
  • startMarkOrOptions <string> | <Object> 可选。
    • detail <any> 附加到度量的可选详细信息。
    • duration <number> 开始和结束时间之间的持续时间。
    • end <number> | <string> 用作结束时间的时间戳,或标识先前记录的标记的字符串。
    • start <number> | <string> 用作开始时间的时间戳,或标识先前记录的标记的字符串。
  • endMark <string> 可选。如果 startMarkOrOptions 是一个 <Object>,则必须省略。

在性能时间线中创建一个新的 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 手动从全局性能时间线中清除这些条目。

performance.nodeTiming#

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

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

performance.now()#

返回当前高精度毫秒时间戳,其中 0 表示当前 node 进程的开始。

performance.setResourceTimingBufferSize(maxSize)#

将全局性能资源计时缓冲区大小设置为指定数量的“resource”类型性能条目对象。

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

performance.timeOrigin#

timeOrigin 指定了当前 node 进程开始时的高精度毫秒时间戳,以 Unix 时间计量。

performance.timerify(fn[, options])#

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

将一个函数包装在一个新函数中,该新函数测量被包装函数的运行时间。必须有一个 PerformanceObserver 订阅 'function' 事件类型,才能访问计时细节。

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

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

const wrapped = performance.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();const {
  performance,
  PerformanceObserver,
} = require('node:perf_hooks');

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

const wrapped = performance.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();

如果被包装的函数返回一个 promise,一个 finally 处理程序将被附加到该 promise 上,并且在 finally 处理程序被调用后报告持续时间。

performance.toJSON()#

一个对象,是 performance 对象的 JSON 表示。它类似于浏览器中的 window.performance.toJSON

事件:'resourcetimingbufferfull'#

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

类:PerformanceEntry#

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

performanceEntry.duration#

此条目经过的总毫秒数。对于所有性能条目类型,此值并非都有意义。

performanceEntry.entryType#

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

  • '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 上可用)

performanceEntry.name#

性能条目的名称。

performanceEntry.startTime#

标记性能条目开始时间的高精度毫秒时间戳。

类:PerformanceMark#

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

performanceMark.detail#

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

类:PerformanceMeasure#

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

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

performanceMeasure.detail#

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

类:PerformanceNodeEntry#

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

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

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

performanceNodeEntry.detail#

特定于 entryType 的附加详细信息。

performanceNodeEntry.flags#

稳定性:0 - 已弃用:请改用 performanceNodeEntry.detail

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

performanceNodeEntry.kind#

稳定性:0 - 已弃用:请改用 performanceNodeEntry.detail

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_INCREMENTAL
  • perf_hooks.constants.NODE_PERFORMANCE_GC_WEAKCB

垃圾回收 ('gc') 详情#

performanceEntry.type 等于 'gc' 时,performanceNodeEntry.detail 属性将是一个具有两个属性的 <Object>

  • kind <number> 以下之一:
    • perf_hooks.constants.NODE_PERFORMANCE_GC_MAJOR
    • perf_hooks.constants.NODE_PERFORMANCE_GC_MINOR
    • 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

HTTP ('http') 详情#

performanceEntry.type 等于 'http' 时,performanceNodeEntry.detail 属性将是一个包含附加信息的 <Object>

如果 performanceEntry.name 等于 HttpClientdetail 将包含以下属性:reqres。并且 req 属性将是一个包含 methodurlheaders<Object>res 属性将是一个包含 statusCodestatusMessageheaders<Object>

如果 performanceEntry.name 等于 HttpRequestdetail 将包含以下属性:reqres。并且 req 属性将是一个包含 methodurlheaders<Object>res 属性将是一个包含 statusCodestatusMessageheaders<Object>

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

HTTP/2 ('http2') 详情#

performanceEntry.type 等于 'http2' 时,performanceNodeEntry.detail 属性将是一个包含附加性能信息的 <Object>

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

  • bytesRead <number> 为此 Http2Stream 接收的 DATA 帧字节数。
  • bytesWritten <number> 为此 Http2Stream 发送的 DATA 帧字节数。
  • id <number> 相关 Http2Stream 的标识符
  • timeToFirstByte <number>PerformanceEntrystartTime 到接收到第一个 DATA 帧所经过的毫秒数。
  • timeToFirstByteSent <number>PerformanceEntrystartTime 到发送第一个 DATA 帧所经过的毫秒数。
  • timeToFirstHeader <number>PerformanceEntrystartTime 到接收到第一个标头所经过的毫秒数。

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

  • 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 实例数。
  • type <string> 'server''client',用于标识 Http2Session 的类型。

计时器化 ('function') 详情#

performanceEntry.type 等于 'function' 时,performanceNodeEntry.detail 属性将是一个 <Array>,列出计时函数的输入参数。

网络 ('net') 详情#

performanceEntry.type 等于 'net' 时,performanceNodeEntry.detail 属性将是一个包含附加信息的 <Object>

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

DNS ('dns') 详情#

performanceEntry.type 等于 'dns' 时,performanceNodeEntry.detail 属性将是一个包含附加信息的 <Object>

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

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

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

类:PerformanceNodeTiming#

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

提供 Node.js 本身的计时细节。此类的构造函数不会直接暴露给用户。

performanceNodeTiming.bootstrapComplete#

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

performanceNodeTiming.environment#

Node.js 环境被初始化时的高精度毫秒时间戳。

performanceNodeTiming.idleTime#

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

performanceNodeTiming.loopExit#

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

performanceNodeTiming.loopStart#

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

performanceNodeTiming.nodeStart#

Node.js 进程被初始化时的高精度毫秒时间戳。

performanceNodeTiming.uvMetricsInfo#

  • 返回:<Object>
    • loopCount <number> 事件循环迭代次数。
    • events <number> 已被事件处理程序处理的事件数。
    • eventsWaiting <number> 当事件提供者被调用时等待处理的事件数。

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

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

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

setImmediate(() => {
  console.log(performance.nodeTiming.uvMetricsInfo);
});import { performance } from 'node:perf_hooks';

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

performanceNodeTiming.v8Start#

V8 平台被初始化时的高精度毫秒时间戳。

类:PerformanceResourceTiming#

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

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

performanceResourceTiming.workerStart#

在分派 fetch 请求之前立即的高精度毫秒时间戳。如果资源未被工作线程拦截,该属性将始终返回 0。

performanceResourceTiming.redirectStart#

代表发起重定向的 fetch 开始时间的高精度毫秒时间戳。

performanceResourceTiming.redirectEnd#

将在接收到最后一个重定向的响应的最后一个字节后立即创建的高精度毫秒时间戳。

performanceResourceTiming.fetchStart#

在 Node.js 开始获取资源之前立即的高精度毫秒时间戳。

performanceResourceTiming.domainLookupStart#

在 Node.js 开始为资源进行域名查找之前立即的高精度毫秒时间戳。

performanceResourceTiming.domainLookupEnd#

代表 Node.js 完成为资源进行域名查找之后立即的时间的高精度毫秒时间戳。

performanceResourceTiming.connectStart#

代表 Node.js 开始建立到服务器的连接以检索资源之前立即的时间的高精度毫秒时间戳。

performanceResourceTiming.connectEnd#

代表 Node.js 完成建立到服务器的连接以检索资源之后立即的时间的高精度毫秒时间戳。

performanceResourceTiming.secureConnectionStart#

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

performanceResourceTiming.requestStart#

代表 Node.js 从服务器接收到响应的第一个字节之前立即的时间的高精度毫秒时间戳。

performanceResourceTiming.responseEnd#

代表 Node.js 接收到资源的最后一个字节之后立即,或在传输连接关闭之前立即的时间的高精度毫秒时间戳,以先到者为准。

performanceResourceTiming.transferSize#

表示获取的资源大小(以八位字节为单位)的数字。大小包括响应头字段和响应有效载荷主体。

performanceResourceTiming.encodedBodySize#

表示从获取(HTTP 或缓存)中接收到的有效载荷主体的大小(以八位字节为单位),在移除任何应用的内容编码之前。

performanceResourceTiming.decodedBodySize#

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

performanceResourceTiming.toJSON()#

返回一个 object,它是 PerformanceResourceTiming 对象的 JSON 表示

类:PerformanceObserver#

PerformanceObserver.supportedEntryTypes#

获取支持的类型。

new PerformanceObserver(callback)#

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');const {
  performance,
  PerformanceObserver,
} = require('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.disconnect()#

断开 PerformanceObserver 实例与所有通知的连接。

performanceObserver.observe(options)#

  • options <Object>
    • type <string> 单个 <PerformanceEntry> 类型。如果已指定 entryTypes,则不得提供此项。
    • entryTypes <string[]> 一个字符串数组,用于标识观察者感兴趣的 <PerformanceEntry> 实例的类型。如果未提供,将抛出错误。
    • buffered <boolean> 如果为 true,则使用全局 PerformanceEntry 缓冲条目列表调用观察者回调。如果为 false,则只有在该时间点之后创建的 PerformanceEntrys 会发送到观察者回调。默认值: false

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

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

const obs = new PerformanceObserver((list, observer) => {
  // Called once asynchronously. `list` contains three items.
});
obs.observe({ type: 'mark' });

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

const obs = new PerformanceObserver((list, observer) => {
  // Called once asynchronously. `list` contains three items.
});
obs.observe({ type: 'mark' });

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

performanceObserver.takeRecords()#

  • 返回:<PerformanceEntry[]> 当前存储在性能观察者中的条目列表,并将其清空。

类:PerformanceObserverEntryList#

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

performanceObserverEntryList.getEntries()#

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

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');const {
  performance,
  PerformanceObserver,
} = require('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');

performanceObserverEntryList.getEntriesByName(name[, type])#

返回一个按 performanceEntry.startTime 时间顺序排列的 PerformanceEntry 对象列表,其 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');const {
  performance,
  PerformanceObserver,
} = require('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');

performanceObserverEntryList.getEntriesByType(type)#

返回一个按 performanceEntry.startTime 时间顺序排列的 PerformanceEntry 对象列表,其 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');const {
  performance,
  PerformanceObserver,
} = require('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');

perf_hooks.createHistogram([options])#

  • options <Object>
    • lowest <number> | <bigint> 最低可辨别值。必须是大于 0 的整数值。默认值: 1
    • highest <number> | <bigint> 最高可记录值。必须是等于或大于两倍 lowest 的整数值。默认值: Number.MAX_SAFE_INTEGER
    • figures <number> 精度位数。必须是 15 之间的数字。默认值: 3
  • 返回:<RecordableHistogram>

返回一个 <RecordableHistogram>

perf_hooks.monitorEventLoopDelay([options])#

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

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

使用计时器来检测近似的事件循环延迟是可行的,因为计时器的执行与 libuv 事件循环的生命周期特定地联系在一起。也就是说,循环中的延迟会导致计时器执行的延迟,而这些延迟正是此 API 旨在检测的。

import { monitorEventLoopDelay } from 'node:perf_hooks';

const h = monitorEventLoopDelay({ resolution: 20 });
h.enable();
// Do something.
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));const { monitorEventLoopDelay } = require('node:perf_hooks');
const h = monitorEventLoopDelay({ resolution: 20 });
h.enable();
// Do something.
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));

类:Histogram#

histogram.count#

直方图记录的样本数。

histogram.countBigInt#

直方图记录的样本数。

histogram.exceeds#

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

histogram.exceedsBigInt#

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

histogram.max#

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

histogram.maxBigInt#

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

histogram.mean#

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

histogram.min#

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

histogram.minBigInt#

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

histogram.percentile(percentile)#

  • percentile <number> 范围在 (0, 100] 内的百分位数值。
  • 返回:<number>

返回给定百分位的值。

histogram.percentileBigInt(percentile)#

  • percentile <number> 范围在 (0, 100] 内的百分位数值。
  • 返回:<bigint>

返回给定百分位的值。

histogram.percentiles#

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

histogram.percentilesBigInt#

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

histogram.reset()#

重置收集的直方图数据。

histogram.stddev#

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

类:IntervalHistogram extends Histogram#

一个在给定间隔内定期更新的 Histogram

histogram.disable()#

禁用更新间隔计时器。如果计时器被停止,则返回 true,如果它已经停止,则返回 false

histogram.enable()#

启用更新间隔计时器。如果计时器被启动,则返回 true,如果它已经启动,则返回 false

histogram[Symbol.dispose]()#

在直方图被销毁时禁用更新间隔计时器。

const { monitorEventLoopDelay } = require('node:perf_hooks');
{
  using hist = monitorEventLoopDelay({ resolution: 20 });
  hist.enable();
  // The histogram will be disabled when the block is exited.
} 

克隆一个 IntervalHistogram#

<IntervalHistogram> 实例可以通过 <MessagePort> 进行克隆。在接收端,直方图被克隆为一个普通的 <Histogram> 对象,它不实现 enable()disable() 方法。

类:RecordableHistogram extends Histogram#

histogram.add(other)#

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

histogram.record(val)#

histogram.recordDelta()#

计算自上次调用 recordDelta() 以来经过的时间(以纳秒为单位),并在直方图中记录该量。

示例#

测量异步操作的持续时间#

以下示例使用 Async Hooks 和 Performance API 来测量 Timeout 操作的实际持续时间(包括执行回调所需的时间)。

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);'use strict';
const async_hooks = require('node:async_hooks');
const {
  performance,
  PerformanceObserver,
} = require('node:perf_hooks');

const set = new Set();
const hook = async_hooks.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'] });

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

测量加载依赖项所需的时间#

以下示例测量 require() 操作加载依赖项的持续时间

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

// Activate the observer
const obs = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  entries.forEach((entry) => {
    console.log(`import('${entry[0]}')`, entry.duration);
  });
  performance.clearMarks();
  performance.clearMeasures();
  obs.disconnect();
});
obs.observe({ entryTypes: ['function'], buffered: true });

const timedImport = performance.timerify(async (module) => {
  return await import(module);
});

await timedImport('some-module');'use strict';
const {
  performance,
  PerformanceObserver,
} = require('node:perf_hooks');
const mod = require('node:module');

// Monkey patch the require function
mod.Module.prototype.require =
  performance.timerify(mod.Module.prototype.require);
require = performance.timerify(require);

// Activate the observer
const obs = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  entries.forEach((entry) => {
    console.log(`require('${entry[0]}')`, entry.duration);
  });
  performance.clearMarks();
  performance.clearMeasures();
  obs.disconnect();
});
obs.observe({ entryTypes: ['function'] });

require('some-module');

测量一次 HTTP 往返所需的时间#

以下示例用于跟踪 HTTP 客户端 (OutgoingMessage) 和 HTTP 请求 (IncomingMessage) 所花费的时间。对于 HTTP 客户端,它表示从启动请求到接收响应的时间间隔,对于 HTTP 请求,它表示从接收请求到发送响应的时间间隔。

import { PerformanceObserver } from 'node:perf_hooks';
import { createServer, get } from 'node:http';

const obs = new PerformanceObserver((items) => {
  items.getEntries().forEach((item) => {
    console.log(item);
  });
});

obs.observe({ entryTypes: ['http'] });

const PORT = 8080;

createServer((req, res) => {
  res.end('ok');
}).listen(PORT, () => {
  get(`http://127.0.0.1:${PORT}`);
});'use strict';
const { PerformanceObserver } = require('node:perf_hooks');
const http = require('node:http');

const obs = new PerformanceObserver((items) => {
  items.getEntries().forEach((item) => {
    console.log(item);
  });
});

obs.observe({ entryTypes: ['http'] });

const PORT = 8080;

http.createServer((req, res) => {
  res.end('ok');
}).listen(PORT, () => {
  http.get(`http://127.0.0.1:${PORT}`);
});

测量连接成功时 net.connect (仅 TCP) 所需的时间#

import { PerformanceObserver } from 'node:perf_hooks';
import { connect, createServer } from 'node:net';

const obs = new PerformanceObserver((items) => {
  items.getEntries().forEach((item) => {
    console.log(item);
  });
});
obs.observe({ entryTypes: ['net'] });
const PORT = 8080;
createServer((socket) => {
  socket.destroy();
}).listen(PORT, () => {
  connect(PORT);
});'use strict';
const { PerformanceObserver } = require('node:perf_hooks');
const net = require('node:net');
const obs = new PerformanceObserver((items) => {
  items.getEntries().forEach((item) => {
    console.log(item);
  });
});
obs.observe({ entryTypes: ['net'] });
const PORT = 8080;
net.createServer((socket) => {
  socket.destroy();
}).listen(PORT, () => {
  net.connect(PORT);
});

测量请求成功时 DNS 所需的时间#

import { PerformanceObserver } from 'node:perf_hooks';
import { lookup, promises } from 'node:dns';

const obs = new PerformanceObserver((items) => {
  items.getEntries().forEach((item) => {
    console.log(item);
  });
});
obs.observe({ entryTypes: ['dns'] });
lookup('localhost', () => {});
promises.resolve('localhost');'use strict';
const { PerformanceObserver } = require('node:perf_hooks');
const dns = require('node:dns');
const obs = new PerformanceObserver((items) => {
  items.getEntries().forEach((item) => {
    console.log(item);
  });
});
obs.observe({ entryTypes: ['dns'] });
dns.lookup('localhost', () => {});
dns.promises.resolve('localhost');