效能測量 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');