On this page

性能测量 API

History
Source Code: lib/perf_hooks.js

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

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

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

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

perf_hooks.performance

History

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

performance.clearMarks(name?): void
Attributes
name:string

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

performance.clearMeasures(name?): void
Attributes
name:string

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

performance.clearResourceTimings(name?): void
Attributes
name:string

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

performance.eventLoopUtilization(utilization1?, utilization2?): void
Attributes
utilization1:Object
之前调用 eventLoopUtilization() 的结果。
utilization2:Object
utilization1 之前调用 eventLoopUtilization() 的结果。
idle:number
active:number
utilization:number

这是 perf_hooks.eventLoopUtilization() 的别名。

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

performance.getEntries(): void

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

performance.getEntriesByName(name, type?): void
Attributes
name:string
type:string

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

performance.getEntriesByType(type): void
Attributes
type:string

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

performance.mark(name, options?): void
Attributes
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?): void
Attributes
timingInfo:Object
[获取时序信息][]
requestedUrl:string
资源 URL
initiatorType:string
发起者名称,例如:'fetch'
global:Object
cacheMode:string
缓存模式必须是空字符串 ('') 或 'local'
responseStatus:number
响应的状态码
deliveryType:string
交付类型。 默认值: ''

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

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

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

performance.measure(name, startMarkOrOptions?, endMark?): void
Attributes
name:string
startMarkOrOptions:string | Object
可选。
detail:any
包含在测量中的附加可选详情。
duration:number
开始和结束时间之间的持续时间。
用作结束时间的时间戳,或标识先前记录的标记的字符串。
start:number | string
用作开始时间的时间戳,或标识先前记录的标记的字符串。
endMark:string
可选。如果 startMarkOrOptionsObject ,则必须省略。

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

P

performance.nodeTiming

History

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

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

performance.now(): void

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

performance.setResourceTimingBufferSize(maxSize): void

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

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

P

performance.timeOrigin

History

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

performance.timerify(fn, options?): void
Attributes
options:Object
使用 perf_hooks.createHistogram() 创建的直方图对象,将记录纳秒级的运行时持续时间。

这是 perf_hooks.timerify() 的别名。

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

performance.toJSON(): void

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

事件:'resourcetimingbufferfull'

History

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

类:PerformanceEntry

History

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

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

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

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

性能条目的名称。

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

类:PerformanceMark

History

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

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

类:PerformanceMeasure

History

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

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

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

类:PerformanceNodeEntry

History

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

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

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

特定于 entryType 的附加详情。

稳定性: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

稳定性: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_MINOR_MARK_SWEEP
  • perf_hooks.constants.NODE_PERFORMANCE_GC_INCREMENTAL
  • perf_hooks.constants.NODE_PERFORMANCE_GC_WEAKCB

performanceEntry.type 等于 'gc' 时,performanceNodeEntry.detail 属性将是一个包含两个属性的 Object

Attributes
kind:number
以下之一:
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.type 等于 'http' 时,performanceNodeEntry.detail 属性将是一个包含附加信息的 Object

如果 performanceEntry.name 等于 HttpClientdetail 将包含以下属性:reqresreq 属性将是一个包含 methodurlheadersObjectres 属性将是一个包含 statusCodestatusMessageheadersObject

如果 performanceEntry.name 等于 HttpRequestdetail 将包含以下属性:reqresreq 属性将是一个包含 methodurlheadersObjectres 属性将是一个包含 statusCodestatusMessageheadersObject

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

performanceEntry.type 等于 'http2' 时,performanceNodeEntry.detail 属性将是一个包含附加性能信息的 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 实例数。
type:string
'server''client' ,用于标识 Http2Session 的类型。

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

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

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

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

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

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

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

类:PerformanceNodeTiming

History

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

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

P

performanceNodeTiming.bootstrapComplete

History

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

P

performanceNodeTiming.environment

History

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

P

performanceNodeTiming.idleTime

History

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

P

performanceNodeTiming.loopExit

History

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

P

performanceNodeTiming.loopStart

History

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

P

performanceNodeTiming.nodeStart

History

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

P

performanceNodeTiming.uvMetricsInfo

History
  • 返回:Object
    Attributes
    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);
});
P

performanceNodeTiming.v8Start

History

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

类:PerformanceResourceTiming

History

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

performanceResourceTiming.toJSON(): void

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

类:PerformanceObserver

History
P

PerformanceObserver.supportedEntryTypes

History

获取支持的类型。

new PerformanceObserver(callback): void
Attributes

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 的引用。

M

performanceObserver.disconnect

History
performanceObserver.disconnect(): void

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

performanceObserver.observe(options): void
Attributes
options:Object
type:string
单个 PerformanceEntry 类型。如果已指定 entryTypes ,则不得给定。
entryTypes:string[]
一个字符串数组,标识观察者感兴趣的 PerformanceEntry 实例的类型。如果未提供,将抛出错误。
buffered:boolean
如果为 true,观察者回调将被调用并传入全局 PerformanceEntry 缓冲条目列表。如果为 false,只有时间点之后创建的 PerformanceEntry 才会发送给观察者回调。 默认值: false

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

performanceObserver.takeRecords

History
performanceObserver.takeRecords(): void
  • 返回:PerformanceEntry[] 当前存储在性能观察者中的条目列表,并将其清空。

类:PerformanceObserverEntryList

History

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

M

performanceObserverEntryList.getEntries

History
performanceObserverEntryList.getEntries(): void

返回一个 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');
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');
M

performanceObserverEntryList.getEntriesByName

History
performanceObserverEntryList.getEntriesByName(name, type?): void
Attributes
name:string
type:string

返回一个 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');
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');
M

performanceObserverEntryList.getEntriesByType

History
performanceObserverEntryList.getEntriesByType(type): void
Attributes
type:string

返回一个 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');
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');
M

perf_hooks.createHistogram

History
perf_hooks.createHistogram(options?): void
Attributes
options:Object
lowest:number | bigint
最低可分辨值。必须是大于 0 的整数值。 默认值: 1
highest:number | bigint
最高可记录值。必须是等于或大于 lowest 两倍的整数值。 默认值: Number.MAX_SAFE_INTEGER
figures:number
精度位数。必须是 15 之间的数字。 默认值: 3

返回一个 RecordableHistogram

M

perf_hooks.eventLoopUtilization

History
perf_hooks.eventLoopUtilization(utilization1?, utilization2?): void
Attributes
utilization1:Object
之前调用 eventLoopUtilization() 的结果。
utilization2:Object
utilization1 之前调用 eventLoopUtilization() 的结果。
idle:number
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);
});
const { eventLoopUtilization } = require('node:perf_hooks');
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() 的结果会导致未定义的行为。返回值不保证反映事件循环的任何正确状态。

perf_hooks.monitorEventLoopDelay(options?): void
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));
const { monitorEventLoopDelay } = require('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));
M

perf_hooks.timerify

History
perf_hooks.timerify(fn, options?): void
Attributes
options:Object
使用 perf_hooks.createHistogram() 创建的直方图对象,用于记录以纳秒为单位的运行时长。

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

将函数包装在一个新函数中,以测量被包装函数的运行时长。必须订阅 'function' 条目类型的 PerformanceObserver 才能访问计时详情。

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'] });

// 将创建一个性能时间线条目
wrapped();
const {
  timerify,
  performance,
  PerformanceObserver,
} = require('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'] });

// 将创建一个性能时间线条目
wrapped();

如果被包装的函数返回一个 promise,则会向该 promise 附加一个 finally 处理程序,并在调用 finally 处理程序后报告时长。

类:Histogram

History
P

histogram.count

History

直方图记录的样本数。

P

histogram.countBigInt

History

直方图记录的样本数。

M

histogram.ccdf

History
histogram.ccdf(value): void
Attributes
value:number
要查询的值。

返回给定值的互补累积分布函数(CCDF)值,表示记录值超过 value 的概率。等价于 1 - histogram.cdf(value)

M

histogram.cdf

History
histogram.cdf(value): void
Attributes
value:number
要查询的值。

返回给定值的累积分布函数(CDF)值,表示记录值小于或等于 value 的概率。这是 histogram.percentile() 的逆操作。

M

histogram.countAt

History
histogram.countAt(value): void
Attributes
value:number
要查询的值。

返回落在给定值对应值范围内的记录值数量。

P

histogram.exceeds

History

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

P

histogram.exceedsBigInt

History

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

M

histogram.ksTest

History
histogram.ksTest(other): void
Attributes
other:Histogram
要与之比较的直方图。

计算此直方图的分布与 other 的比较结果的 Kolmogorov-Smirnov 检验统计量。值为 0 表示分布完全相同;接近 1 的值表示分布完全不相交。 通过比较变更前后的直方图,可用于检测性能回归。

P

histogram.kurtosis

History

记录值的超额峰度。用于衡量分布尾部相对于正态分布的厚重程度。正值 表示尾部较厚(极端离群值更多);负值表示尾部较轻。

M

histogram.linearBuckets

History
histogram.linearBuckets(stepSize): void
Attributes
stepSize:number
每个线性桶的宽度。

返回按 stepSize 重新划分为等间距区间的直方图数据。 适用于可视化和导出。

M

histogram.logBuckets

History
histogram.logBuckets(firstBucket, base): void
Attributes
firstBucket:number
第一个桶边界的值。
base:number
桶宽度增长所使用的对数基数。必须大于 1。

返回重新划分为对数间距区间的直方图数据,其中每个桶的宽度乘以 base。适用于可视化和导出。

P

histogram.max

History

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

P

histogram.maxBigInt

History

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

P

histogram.mean

History

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

P

histogram.min

History

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

P

histogram.minBigInt

History

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

M

histogram.percentile

History
histogram.percentile(percentile): void
Attributes
percentile:number
范围在 (0, 100] 内的百分位值。

返回给定百分位处的值。

M

histogram.percentileBigInt

History
histogram.percentileBigInt(percentile): void
Attributes
percentile:number
范围在 (0, 100] 内的百分位值。

返回给定百分位处的值。

P

histogram.percentiles

History

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

P

histogram.percentilesBigInt

History

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

M

histogram.percentilesAt

History
histogram.percentilesAt(percentiles): void
Attributes
percentiles:number[]
范围在 (0, 100] 内的百分位值数组。

返回指定百分位处的值,在一次高效遍历直方图数据的过程中计算得出。 比多次调用 histogram.percentile() 更高效。

M

histogram.reset

History
histogram.reset(): void

重置收集的直方图数据。

P

histogram.skewness

History

记录值的偏度。用于衡量分布的不对称性。正值表示右偏分布 (右尾更长,延迟数据中较为常见);负值表示左偏分布。

P

histogram.stddev

History

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

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

M

histogram.disable

History
histogram.disable(): void

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

M

histogram.enable

History
histogram.enable(): void

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

M

histogram[Symbol.dispose]

History
histogram[Symbol.dispose](): void

在直方图被释放时禁用事件循环延迟采样。

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

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

类:RecordableHistogram extends Histogram

History
M

histogram.add

History
histogram.add(other): void
Attributes

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

M

histogram.record

History
histogram.record(val): void
Attributes
要记录到直方图中的量。
M

histogram.recordDelta

History
histogram.recordDelta(): void

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

M

histogram.recordCorrected

History
histogram.recordCorrected(val, expectedInterval): void
Attributes
要记录的值。
expectedInterval:number | bigint
预期的记录间隔。

使用协调遗漏校正记录一个值。当系统停顿导致无法及时记录时,此方法会在上次记录的值与 val 之间,以 expectedInterval 为步长补录中间值。这样可以弥补测量间隔,否则这些间隔会导致延迟被低估。

M

histogram.subtract

History
histogram.subtract(other): void
Attributes

从此直方图中减去 other 的值。两个直方图应具有兼容的配置。可能变为负数的桶计数会被限制为零。

Histogram 类提供了适用于性能监控、SLO 执行和回归检测的统计分析方法。

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

const h = createHistogram();

// Simulate a right-skewed latency distribution
for (let i = 0; i < 1000; i++) {
  h.record(Math.ceil(Math.random() * 100));
}
// Add some outliers
for (let i = 0; i < 10; i++) {
  h.record(500 + Math.ceil(Math.random() * 500));
}

console.log('Skewness:', h.skewness.toFixed(4));  // Positive = right-skewed
console.log('Kurtosis:', h.kurtosis.toFixed(4));  // Positive = heavy tails
const { createHistogram } = require('node:perf_hooks');

const latency = createHistogram();

// Record request latencies (in nanoseconds)...

// "What fraction of requests complete within 100ms?"
const withinSLO = latency.cdf(100_000_000);
console.log(`${(withinSLO * 100).toFixed(1)}% of requests within SLO`);

// "What fraction of requests exceed 500ms?"
const violating = latency.ccdf(500_000_000);
console.log(`${(violating * 100).toFixed(1)}% of requests violating SLO`);
const { createHistogram } = require('node:perf_hooks');

const baseline = createHistogram();
const current = createHistogram();

// Record baseline and current latencies...

// D-statistic: 0 = identical, 1 = completely different
const d = baseline.ksTest(current);
if (d > 0.1) {
  console.log(`Possible regression detected (D=${d.toFixed(4)})`);
}
const { createHistogram } = require('node:perf_hooks');

const h = createHistogram();
// Record values...

// Efficiently query common monitoring percentiles in one pass
const p = h.percentilesAt([50, 75, 90, 95, 99, 99.9]);
console.log('p50:', p.get(50));
console.log('p99:', p.get(99));
const { createHistogram } = require('node:perf_hooks');

const total = createHistogram();
const snapshot = createHistogram();

// Record values into total...
// Periodically snapshot for "last interval" analysis:
snapshot.add(total);

// Later, take a new snapshot and diff:
const newSnapshot = createHistogram();
newSnapshot.add(total);
newSnapshot.subtract(snapshot);
// newSnapshot now contains only the values recorded since the last snapshot
console.log('Recent p99:', newSnapshot.percentile(99));

以下示例使用 [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);
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';

// 激活观察器
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');
const {
  performance,
  PerformanceObserver,
} = require('node:perf_hooks');
const mod = require('node:module');

// 猴子补丁 require 函数
mod.Module.prototype.require =
  performance.timerify(mod.Module.prototype.require);
require = performance.timerify(require);

// 激活观察器
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 客户端(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}`);
});
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}`);
});
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);
});
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);
});
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');
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');