Skip to content

性能测量 API

[稳定版: 2 - 稳定版]

稳定版: 2 稳定性: 2 - 稳定版

源代码: lib/perf_hooks.js

此模块提供 W3C Web 性能 API 的子集实现,以及 Node.js 特定性能测量的附加 API。

Node.js 支持以下 Web 性能 API

js
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')
})
js
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

新增于: v8.5.0

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

performance.clearMarks([name])

[历史]

版本变更
v19.0.0此方法必须使用 performance 对象作为接收者调用。
v8.5.0新增于: v8.5.0

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

performance.clearMeasures([name])

[历史]

版本变更
v19.0.0此方法必须使用 performance 对象作为接收者调用。
v16.7.0新增于: v16.7.0

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

performance.clearResourceTimings([name])

[历史]

版本变更
v19.0.0此方法必须使用 performance 对象作为接收者调用。
v18.2.0, v16.17.0新增于:v18.2.0, v16.17.0

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

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

新增于:v14.10.0, v12.19.0

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

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

utilization1utilization2 都是可选参数。

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

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

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

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

setImmediate(() => {
  const elu = eventLoopUtilization()
  spawnSync('sleep', ['5'])
  console.log(eventLoopUtilization(elu).utilization)
})
js
'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()

[历史]

版本变更
v19.0.0此方法必须使用 performance 对象作为接收者调用。
v16.7.0新增于:v16.7.0

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

performance.getEntriesByName(name[, type])

[历史]

版本变更
v19.0.0此方法必须使用 performance 对象作为接收者调用。
v16.7.0新增于:v16.7.0

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

performance.getEntriesByType(type)

[历史]

版本变更
v19.0.0此方法必须使用 performance 对象作为接收者调用。
v16.7.0新增于:v16.7.0

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

performance.mark(name[, options])

[历史]

版本变更
v19.0.0此方法必须使用 performance 对象作为接收者调用。name 参数不再是可选的。
v16.0.0更新为符合用户计时级别 3 规范。
v8.5.0新增于:v8.5.0
  • name <字符串>
  • options <对象>
    • detail <任意> 可选的附加细节,包含在标记中。
    • startTime <数字> 可选的时间戳,用作标记时间。默认值: 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])

[历史]

版本变更
v22.2.0添加了 bodyInforesponseStatusdeliveryType 参数。
v18.2.0, v16.17.0在 v18.2.0, v16.17.0 版本中添加

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

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

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

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

[历史]

版本变更
v19.0.0此方法必须使用 performance 对象作为接收者调用。
v16.0.0更新为符合用户计时级别 3 规范。
v13.13.0, v12.16.3使 startMarkendMark 参数可选。
v8.5.0在 v8.5.0 中添加

在性能时间线中创建一个新的 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

新增于:v8.5.0

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

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

performance.now()

[历史]

版本变更
v19.0.0此方法必须使用 performance 对象作为接收者来调用。
v8.5.0新增于:v8.5.0

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

performance.setResourceTimingBufferSize(maxSize)

[历史]

版本变更
v19.0.0此方法必须使用 performance 对象作为接收者来调用。
v18.8.0新增于:v18.8.0

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

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

performance.timeOrigin

新增于:v8.5.0

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

performance.timerify(fn[, options])

[历史]

版本变更
v16.0.0添加了直方图选项。
v16.0.0重新实现为使用纯 JavaScript 并能够计时异步函数。
v8.5.0新增于:v8.5.0

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

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

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

// 将创建一个性能时间线条目
wrapped()
js
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'] })

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

如果包装的函数返回一个 Promise,则会将 finally 处理程序附加到 Promise,并且一旦调用 finally 处理程序,就会报告持续时间。

performance.toJSON()

[历史]

版本变更
v19.0.0此方法必须使用 performance 对象作为接收者来调用。
v16.1.0新增于:v16.1.0

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

事件:'resourcetimingbufferfull'

新增于:v18.8.0

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

类:PerformanceEntry

新增于:v8.5.0

此类的构造函数不会直接公开给用户。

performanceEntry.duration

[历史]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceEntry 对象作为接收者来调用。
v8.5.0新增于:v8.5.0

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

performanceEntry.entryType

[历史]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceEntry 对象作为接收者来调用。
v8.5.0在 v8.5.0 中添加

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

  • '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

[历史]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceEntry 对象作为接收者来调用。
v8.5.0在 v8.5.0 中添加

性能条目的名称。

performanceEntry.startTime

[历史记录]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceEntry 对象作为接收者来调用。
v8.5.0在 v8.5.0 中添加

表示性能记录起始时间的高精度毫秒时间戳。

类: PerformanceMark

在以下版本中添加: v18.2.0, v16.17.0

公开通过 Performance.mark() 方法创建的标记。

performanceMark.detail

[历史记录]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceMark 对象作为接收者来调用。
v16.0.0在 v16.0.0 中添加

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

类: PerformanceMeasure

新增于: v18.2.0, v16.17.0

公开通过 Performance.measure() 方法创建的度量。

此类的构造函数不会直接向用户公开。

performanceMeasure.detail

[历史]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceMeasure 对象作为接收者来调用。
v16.0.0新增于: v16.0.0

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

类: PerformanceNodeEntry

新增于: v19.0.0

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

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

此类的构造函数不会直接向用户公开。

performanceNodeEntry.detail

[历史]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceNodeEntry 对象作为接收者来调用。
v16.0.0新增于: v16.0.0

特定于 entryType 的附加细节。

performanceNodeEntry.flags

[历史]

版本变更
v16.0.0运行时已弃用。现在已移动到 entryType 为 'gc' 时的 detail 属性中。
v13.9.0, v12.17.0添加于:v13.9.0, v12.17.0

[稳定性: 0 - 已弃用]

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

[历史]

版本变更
v16.0.0运行时已弃用。现在已移动到 entryType 为 'gc' 时的 detail 属性。
v8.5.0新增于:v8.5.0

[稳定性:0 - 已弃用]

稳定性:0 稳定性: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 属性将是一个 <对象>,包含两个属性:

  • 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
  • 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

HTTP ('http') 详情

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

如果 performanceEntry.name 等于 HttpClient,则 detail 将包含以下属性:reqresreq 属性将是一个包含 methodurlheaders<对象>res 属性将是一个包含 statusCodestatusMessageheaders<对象>

如果 performanceEntry.name 等于 HttpRequest,则 detail 将包含以下属性:reqresreq 属性将是一个包含 methodurlheaders<对象>res 属性将是一个包含 statusCodestatusMessageheaders<对象>

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

HTTP/2 ('http2') 详情

performanceEntry.type 等于 'http2' 时,performanceNodeEntry.detail 属性将是一个包含额外性能信息的 <对象>

如果 performanceEntry.name 等于 Http2Stream,则 detail 将包含以下属性:

  • bytesRead <数字>Http2Stream 收到的 DATA 帧字节数。
  • bytesWritten <数字>Http2Stream 发送的 DATA 帧字节数。
  • id <数字> 关联 Http2Stream 的标识符。
  • timeToFirstByte <数字> PerformanceEntrystartTime 与接收第一个 DATA 帧之间经过的毫秒数。
  • timeToFirstByteSent <数字> PerformanceEntrystartTime 与发送第一个 DATA 帧之间经过的毫秒数。
  • timeToFirstHeader <数字> PerformanceEntrystartTime 与接收第一个报头之间经过的毫秒数。

如果 performanceEntry.name 等于 Http2Session,则 detail 将包含以下属性:

  • bytesRead <数字>Http2Session 收到的字节数。
  • bytesWritten <数字>Http2Session 发送的字节数。
  • framesReceived <数字> Http2Session 收到的 HTTP/2 帧数。
  • framesSent <数字> Http2Session 发送的 HTTP/2 帧数。
  • maxConcurrentStreams <数字> Http2Session 生命周期内同时打开的最大流数。
  • pingRTT <数字> 发送 PING 帧及其应答接收之间经过的毫秒数。只有在 Http2Session 上发送了 PING 帧时才存在。
  • streamAverageDuration <数字> 所有 Http2Stream 实例的平均持续时间(以毫秒为单位)。
  • streamCount <数字> Http2Session 处理的 Http2Stream 实例数。
  • type <字符串> 'server''client',用于标识 Http2Session 的类型。

Timerify ('function') 详情

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

Net ('net') 详情

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

如果 performanceEntry.name 等于 connect,则 detail 将包含以下属性:hostport

DNS ('dns') 详情

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

如果 performanceEntry.name 等于 lookup,则 detail 将包含以下属性:hostnamefamilyhintsverbatimaddresses

如果 performanceEntry.name 等于 lookupService,则 detail 将包含以下属性:hostporthostnameservice

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

类: PerformanceNodeTiming

新增于: v8.5.0

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

提供 Node.js 本身的时间细节。此类的构造函数对用户不可见。

performanceNodeTiming.bootstrapComplete

新增于: v8.5.0

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

performanceNodeTiming.environment

新增于: v8.5.0

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

performanceNodeTiming.idleTime

新增于: v14.10.0, v12.19.0

事件循环在事件循环的事件提供程序(例如 epoll_wait)中空闲的时间的高精度毫秒时间戳。这不会考虑 CPU 使用率。如果事件循环尚未启动(例如,在主脚本的第一个 tick 中),则该属性的值为 0。

performanceNodeTiming.loopExit

新增于: v8.5.0

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

performanceNodeTiming.loopStart

新增于: v8.5.0

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

performanceNodeTiming.nodeStart

新增于: v8.5.0

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

performanceNodeTiming.uvMetricsInfo

新增于: v22.8.0, v20.18.0

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

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

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

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

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

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

performanceNodeTiming.v8Start

新增于: v8.5.0

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

类: PerformanceResourceTiming

新增于: v18.2.0, v16.17.0

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

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

performanceResourceTiming.workerStart

[历史]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceResourceTiming 对象作为接收者来调用。
v18.2.0, v16.17.0新增于: v18.2.0, v16.17.0

在分派 fetch 请求之前的立即高精度毫秒时间戳。如果资源没有被 worker 拦截,则此属性将始终返回 0。

performanceResourceTiming.redirectStart

[历史]

版本变更
v19.0.0此属性 getter 必须以 PerformanceResourceTiming 对象作为接收者来调用。
v18.2.0, v16.17.0添加于:v18.2.0, v16.17.0

表示启动重定向的提取开始时间的高精度毫秒时间戳。

performanceResourceTiming.redirectEnd

[历史]

版本变更
v19.0.0此属性 getter 必须以 PerformanceResourceTiming 对象作为接收者来调用。
v18.2.0, v16.17.0添加于:v18.2.0, v16.17.0

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

performanceResourceTiming.fetchStart

[历史记录]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceResourceTiming 对象作为接收者调用。
v18.2.0, v16.17.0新增于:v18.2.0, v16.17.0

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

performanceResourceTiming.domainLookupStart

[历史记录]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceResourceTiming 对象作为接收者调用。
v18.2.0, v16.17.0新增于:v18.2.0, v16.17.0

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

performanceResourceTiming.domainLookupEnd

[历史记录]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceResourceTiming 对象作为接收者调用。
v18.2.0, v16.17.0新增于:v18.2.0, v16.17.0

表示 Node.js 完成资源域名查找后的毫秒级高精度时间戳。

performanceResourceTiming.connectStart

[历史]

版本变更
v19.0.0此属性 getter 必须以 PerformanceResourceTiming 对象作为接收者来调用。
v18.2.0, v16.17.0新增于:v18.2.0, v16.17.0

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

performanceResourceTiming.connectEnd

[历史]

版本变更
v19.0.0此属性 getter 必须以 PerformanceResourceTiming 对象作为接收者来调用。
v18.2.0, v16.17.0新增于:v18.2.0, v16.17.0

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

performanceResourceTiming.secureConnectionStart

[历史]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceResourceTiming 对象作为接收者来调用。
v18.2.0, v16.17.0新增于:v18.2.0, v16.17.0

表示 Node.js 开始安全连接握手过程之前的毫秒级高精度时间戳。

performanceResourceTiming.requestStart

[历史]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceResourceTiming 对象作为接收者来调用。
v18.2.0, v16.17.0新增于:v18.2.0, v16.17.0

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

performanceResourceTiming.responseEnd

[历史]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceResourceTiming 对象作为接收者调用。
v18.2.0, v16.17.0新增于:v18.2.0, v16.17.0

表示 Node.js 接收资源的最后一个字节之后的时间戳(毫秒级高精度),或传输连接关闭之前的时间戳(以先发生者为准)。

performanceResourceTiming.transferSize

[历史]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceResourceTiming 对象作为接收者调用。
v18.2.0, v16.17.0新增于:v18.2.0, v16.17.0

表示已获取资源大小(以八位字节为单位)的数字。此大小包括响应报头字段和响应有效负载正文。

performanceResourceTiming.encodedBodySize

[历史]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceResourceTiming 对象作为接收者来调用。
v18.2.0, v16.17.0新增于:v18.2.0, v16.17.0

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

performanceResourceTiming.decodedBodySize

[历史]

版本变更
v19.0.0此属性 getter 必须使用 PerformanceResourceTiming 对象作为接收者来调用。
v18.2.0, v16.17.0新增于:v18.2.0, v16.17.0

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

performanceResourceTiming.toJSON()

[历史]

版本变更
v19.0.0此方法必须使用 PerformanceResourceTiming 对象作为接收者来调用。
v18.2.0, v16.17.0新增于:v18.2.0, v16.17.0

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

类: PerformanceObserver

新增于: v8.5.0

PerformanceObserver.supportedEntryTypes

新增于: v16.0.0

获取支持的类型。

new PerformanceObserver(callback)

[历史]

版本变更
v18.0.0将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK
v8.5.0新增于: v8.5.0

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

js
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')
js
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()

新增于:v8.5.0

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

performanceObserver.observe(options)

[历史记录]

版本变更
v16.7.0更新为符合 Performance Timeline Level 2。已添加回 buffered 选项。
v16.0.0更新为符合 User Timing Level 3。已移除 buffered 选项。
v8.5.0新增于:v8.5.0
  • options <对象>
    • type <字符串> 单个 <PerformanceEntry> 类型。如果已指定 entryTypes,则不得给出此值。
    • entryTypes <字符串数组> 一个字符串数组,用于标识观察者感兴趣的 <PerformanceEntry> 实例的类型。如果未提供,则会抛出错误。
    • buffered <布尔值> 如果为 true,则使用全局缓冲的 PerformanceEntry 列表调用观察者回调函数。如果为 false,则只有时间点之后创建的 PerformanceEntry 会发送到观察者回调函数。默认值: false

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

js
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}`)
js
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}`)

performanceObserver.takeRecords()

新增于:v16.0.0

类:PerformanceObserverEntryList

新增于:v8.5.0

PerformanceObserverEntryList 类用于访问传递给 PerformanceObserverPerformanceEntry 实例。此类的构造函数对用户不可见。

performanceObserverEntryList.getEntries()

新增于:v8.5.0

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

js
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')
js
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])

新增于: v8.5.0

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

js
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')
js
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)

新增于:v8.5.0

返回一个 PerformanceEntry 对象列表,这些对象按照 performanceEntry.startTime 的时间顺序排列,并且它们的 performanceEntry.entryType 等于 type

js
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')
js
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])

新增于: v15.9.0, v14.18.0

  • 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])

新增于: v11.10.0

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

创建一个 IntervalHistogram 对象,用于采样和报告一段时间内的事件循环延迟。延迟将以纳秒为单位报告。

使用计时器检测事件循环的近似延迟之所以有效,是因为计时器的执行与 libuv 事件循环的生命周期特别相关。也就是说,循环中的延迟会导致计时器执行延迟,而此 API 正是用于检测这些延迟。

js
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))
js
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))

类: Histogram

新增于: v11.10.0

histogram.count

新增于: v17.4.0, v16.14.0

直方图记录的样本数量。

histogram.countBigInt

新增于: v17.4.0, v16.14.0

直方图记录的样本数量。

histogram.exceeds

新增于: v11.10.0

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

histogram.exceedsBigInt

新增于: v17.4.0, v16.14.0

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

histogram.max

新增于: v11.10.0

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

histogram.maxBigInt

新增于:v17.4.0, v16.14.0

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

histogram.mean

新增于:v11.10.0

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

histogram.min

新增于:v11.10.0

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

histogram.minBigInt

新增于:v17.4.0, v16.14.0

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

histogram.percentile(percentile)

新增于:v11.10.0

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

返回给定百分位数的值。

histogram.percentileBigInt(percentile)

新增于: v17.4.0, v16.14.0

返回给定百分位数的值。

histogram.percentiles

新增于: v11.10.0

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

histogram.percentilesBigInt

新增于: v17.4.0, v16.14.0

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

histogram.reset()

新增于: v11.10.0

重置已收集的直方图数据。

histogram.stddev

新增于: v11.10.0

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

类: IntervalHistogram extends Histogram

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

histogram.disable()

新增于: v11.10.0

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

histogram.enable()

新增于: v11.10.0

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

克隆 IntervalHistogram

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

类: RecordableHistogram extends Histogram

新增于: v15.9.0, v14.18.0

histogram.add(other)

新增于: v17.4.0, v16.14.0

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

histogram.record(val)

新增于: v15.9.0, v14.18.0

histogram.recordDelta()

新增于: v15.9.0, v14.18.0

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

示例

测量异步操作的持续时间

以下示例使用 异步钩子 和性能 API 来测量超时操作的实际持续时间(包括执行回调所花费的时间)。

js
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)
js
'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'], buffered: true })

setTimeout(() => {}, 1000)

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

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

js
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')
js
'use strict'
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'], buffered: true })

require('some-module')

测量一次 HTTP 往返所需时间

以下示例用于追踪 HTTP 客户端 (OutgoingMessage) 和 HTTP 请求 (IncomingMessage) 所花费的时间。对于 HTTP 客户端,这意味着从发出请求到收到响应的时间间隔;对于 HTTP 请求,这意味着从收到请求到发送响应的时间间隔:

js
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}`)
})
js
'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) 连接成功所需时间

js
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)
})
js
'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 请求成功所需时间

js
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')
js
'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')