• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Performance measurement APIs
2
3<!--introduced_in=v8.5.0-->
4
5> Stability: 2 - Stable
6
7<!-- source_link=lib/perf_hooks.js -->
8
9This module provides an implementation of a subset of the W3C
10[Web Performance APIs][] as well as additional APIs for
11Node.js-specific performance measurements.
12
13Node.js supports the following [Web Performance APIs][]:
14
15* [High Resolution Time][]
16* [Performance Timeline][]
17* [User Timing][]
18* [Resource Timing][]
19
20```js
21const { PerformanceObserver, performance } = require('node:perf_hooks');
22
23const obs = new PerformanceObserver((items) => {
24  console.log(items.getEntries()[0].duration);
25  performance.clearMarks();
26});
27obs.observe({ type: 'measure' });
28performance.measure('Start to Now');
29
30performance.mark('A');
31doSomeLongRunningProcess(() => {
32  performance.measure('A to Now', 'A');
33
34  performance.mark('B');
35  performance.measure('A to B', 'A', 'B');
36});
37```
38
39## `perf_hooks.performance`
40
41<!-- YAML
42added: v8.5.0
43-->
44
45An object that can be used to collect performance metrics from the current
46Node.js instance. It is similar to [`window.performance`][] in browsers.
47
48### `performance.clearMarks([name])`
49
50<!-- YAML
51added: v8.5.0
52-->
53
54* `name` {string}
55
56If `name` is not provided, removes all `PerformanceMark` objects from the
57Performance Timeline. If `name` is provided, removes only the named mark.
58
59### `performance.clearMeasures([name])`
60
61<!-- YAML
62added: v16.7.0
63-->
64
65* `name` {string}
66
67If `name` is not provided, removes all `PerformanceMeasure` objects from the
68Performance Timeline. If `name` is provided, removes only the named measure.
69
70### `performance.clearResourceTimings([name])`
71
72<!-- YAML
73added: v18.2.0
74-->
75
76* `name` {string}
77
78If `name` is not provided, removes all `PerformanceResourceTiming` objects from
79the Resource Timeline. If `name` is provided, removes only the named resource.
80
81### `performance.eventLoopUtilization([utilization1[, utilization2]])`
82
83<!-- YAML
84added:
85 - v14.10.0
86 - v12.19.0
87-->
88
89* `utilization1` {Object} The result of a previous call to
90  `eventLoopUtilization()`.
91* `utilization2` {Object} The result of a previous call to
92  `eventLoopUtilization()` prior to `utilization1`.
93* Returns {Object}
94  * `idle` {number}
95  * `active` {number}
96  * `utilization` {number}
97
98The `eventLoopUtilization()` method returns an object that contains the
99cumulative duration of time the event loop has been both idle and active as a
100high resolution milliseconds timer. The `utilization` value is the calculated
101Event Loop Utilization (ELU).
102
103If bootstrapping has not yet finished on the main thread the properties have
104the value of `0`. The ELU is immediately available on [Worker threads][] since
105bootstrap happens within the event loop.
106
107Both `utilization1` and `utilization2` are optional parameters.
108
109If `utilization1` is passed, then the delta between the current call's `active`
110and `idle` times, as well as the corresponding `utilization` value are
111calculated and returned (similar to [`process.hrtime()`][]).
112
113If `utilization1` and `utilization2` are both passed, then the delta is
114calculated between the two arguments. This is a convenience option because,
115unlike [`process.hrtime()`][], calculating the ELU is more complex than a
116single subtraction.
117
118ELU is similar to CPU utilization, except that it only measures event loop
119statistics and not CPU usage. It represents the percentage of time the event
120loop has spent outside the event loop's event provider (e.g. `epoll_wait`).
121No other CPU idle time is taken into consideration. The following is an example
122of how a mostly idle process will have a high ELU.
123
124```js
125'use strict';
126const { eventLoopUtilization } = require('node:perf_hooks').performance;
127const { spawnSync } = require('node:child_process');
128
129setImmediate(() => {
130  const elu = eventLoopUtilization();
131  spawnSync('sleep', ['5']);
132  console.log(eventLoopUtilization(elu).utilization);
133});
134```
135
136Although the CPU is mostly idle while running this script, the value of
137`utilization` is `1`. This is because the call to
138[`child_process.spawnSync()`][] blocks the event loop from proceeding.
139
140Passing in a user-defined object instead of the result of a previous call to
141`eventLoopUtilization()` will lead to undefined behavior. The return values
142are not guaranteed to reflect any correct state of the event loop.
143
144### `performance.getEntries()`
145
146<!-- YAML
147added: v16.7.0
148-->
149
150* Returns: {PerformanceEntry\[]}
151
152Returns a list of `PerformanceEntry` objects in chronological order with
153respect to `performanceEntry.startTime`. If you are only interested in
154performance entries of certain types or that have certain names, see
155`performance.getEntriesByType()` and `performance.getEntriesByName()`.
156
157### `performance.getEntriesByName(name[, type])`
158
159<!-- YAML
160added: v16.7.0
161-->
162
163* `name` {string}
164* `type` {string}
165* Returns: {PerformanceEntry\[]}
166
167Returns a list of `PerformanceEntry` objects in chronological order
168with respect to `performanceEntry.startTime` whose `performanceEntry.name` is
169equal to `name`, and optionally, whose `performanceEntry.entryType` is equal to
170`type`.
171
172### `performance.getEntriesByType(type)`
173
174<!-- YAML
175added: v16.7.0
176-->
177
178* `type` {string}
179* Returns: {PerformanceEntry\[]}
180
181Returns a list of `PerformanceEntry` objects in chronological order
182with respect to `performanceEntry.startTime` whose `performanceEntry.entryType`
183is equal to `type`.
184
185### `performance.mark([name[, options]])`
186
187<!-- YAML
188added: v8.5.0
189changes:
190  - version: v16.0.0
191    pr-url: https://github.com/nodejs/node/pull/37136
192    description: Updated to conform to the User Timing Level 3 specification.
193-->
194
195* `name` {string}
196* `options` {Object}
197  * `detail` {any} Additional optional detail to include with the mark.
198  * `startTime` {number} An optional timestamp to be used as the mark time.
199    **Default**: `performance.now()`.
200
201Creates a new `PerformanceMark` entry in the Performance Timeline. A
202`PerformanceMark` is a subclass of `PerformanceEntry` whose
203`performanceEntry.entryType` is always `'mark'`, and whose
204`performanceEntry.duration` is always `0`. Performance marks are used
205to mark specific significant moments in the Performance Timeline.
206
207The created `PerformanceMark` entry is put in the global Performance Timeline
208and can be queried with `performance.getEntries`,
209`performance.getEntriesByName`, and `performance.getEntriesByType`. When the
210observation is performed, the entries should be cleared from the global
211Performance Timeline manually with `performance.clearMarks`.
212
213### `performance.markResourceTiming(timingInfo, requestedUrl, initiatorType, global, cacheMode)`
214
215<!-- YAML
216added: v18.2.0
217-->
218
219* `timingInfo` {Object} [Fetch Timing Info][]
220* `requestedUrl` {string} The resource url
221* `initiatorType` {string} The initiator name, e.g: 'fetch'
222* `global` {Object}
223* `cacheMode` {string} The cache mode must be an empty string ('') or 'local'
224
225_This property is an extension by Node.js. It is not available in Web browsers._
226
227Creates a new `PerformanceResourceTiming` entry in the Resource Timeline. A
228`PerformanceResourceTiming` is a subclass of `PerformanceEntry` whose
229`performanceEntry.entryType` is always `'resource'`. Performance resources
230are used to mark moments in the Resource Timeline.
231
232The created `PerformanceMark` entry is put in the global Resource Timeline
233and can be queried with `performance.getEntries`,
234`performance.getEntriesByName`, and `performance.getEntriesByType`. When the
235observation is performed, the entries should be cleared from the global
236Performance Timeline manually with `performance.clearResourceTimings`.
237
238### `performance.measure(name[, startMarkOrOptions[, endMark]])`
239
240<!-- YAML
241added: v8.5.0
242changes:
243  - version: v16.0.0
244    pr-url: https://github.com/nodejs/node/pull/37136
245    description: Updated to conform to the User Timing Level 3 specification.
246  - version:
247      - v13.13.0
248      - v12.16.3
249    pr-url: https://github.com/nodejs/node/pull/32651
250    description: Make `startMark` and `endMark` parameters optional.
251-->
252
253* `name` {string}
254* `startMarkOrOptions` {string|Object} Optional.
255  * `detail` {any} Additional optional detail to include with the measure.
256  * `duration` {number} Duration between start and end times.
257  * `end` {number|string} Timestamp to be used as the end time, or a string
258    identifying a previously recorded mark.
259  * `start` {number|string} Timestamp to be used as the start time, or a string
260    identifying a previously recorded mark.
261* `endMark` {string} Optional. Must be omitted if `startMarkOrOptions` is an
262  {Object}.
263
264Creates a new `PerformanceMeasure` entry in the Performance Timeline. A
265`PerformanceMeasure` is a subclass of `PerformanceEntry` whose
266`performanceEntry.entryType` is always `'measure'`, and whose
267`performanceEntry.duration` measures the number of milliseconds elapsed since
268`startMark` and `endMark`.
269
270The `startMark` argument may identify any _existing_ `PerformanceMark` in the
271Performance Timeline, or _may_ identify any of the timestamp properties
272provided by the `PerformanceNodeTiming` class. If the named `startMark` does
273not exist, an error is thrown.
274
275The optional `endMark` argument must identify any _existing_ `PerformanceMark`
276in the Performance Timeline or any of the timestamp properties provided by the
277`PerformanceNodeTiming` class. `endMark` will be `performance.now()`
278if no parameter is passed, otherwise if the named `endMark` does not exist, an
279error will be thrown.
280
281The created `PerformanceMeasure` entry is put in the global Performance Timeline
282and can be queried with `performance.getEntries`,
283`performance.getEntriesByName`, and `performance.getEntriesByType`. When the
284observation is performed, the entries should be cleared from the global
285Performance Timeline manually with `performance.clearMeasures`.
286
287### `performance.nodeTiming`
288
289<!-- YAML
290added: v8.5.0
291-->
292
293* {PerformanceNodeTiming}
294
295_This property is an extension by Node.js. It is not available in Web browsers._
296
297An instance of the `PerformanceNodeTiming` class that provides performance
298metrics for specific Node.js operational milestones.
299
300### `performance.now()`
301
302<!-- YAML
303added: v8.5.0
304-->
305
306* Returns: {number}
307
308Returns the current high resolution millisecond timestamp, where 0 represents
309the start of the current `node` process.
310
311### `performance.setResourceTimingBufferSize(maxSize)`
312
313<!-- YAML
314added: v18.8.0
315-->
316
317Sets the global performance resource timing buffer size to the specified number
318of "resource" type performance entry objects.
319
320By default the max buffer size is set to 250.
321
322### `performance.timeOrigin`
323
324<!-- YAML
325added: v8.5.0
326-->
327
328* {number}
329
330The [`timeOrigin`][] specifies the high resolution millisecond timestamp at
331which the current `node` process began, measured in Unix time.
332
333### `performance.timerify(fn[, options])`
334
335<!-- YAML
336added: v8.5.0
337changes:
338  - version: v16.0.0
339    pr-url: https://github.com/nodejs/node/pull/37475
340    description: Added the histogram option.
341  - version: v16.0.0
342    pr-url: https://github.com/nodejs/node/pull/37136
343    description: Re-implemented to use pure-JavaScript and the ability
344                 to time async functions.
345-->
346
347* `fn` {Function}
348* `options` {Object}
349  * `histogram` {RecordableHistogram} A histogram object created using
350    `perf_hooks.createHistogram()` that will record runtime durations in
351    nanoseconds.
352
353_This property is an extension by Node.js. It is not available in Web browsers._
354
355Wraps a function within a new function that measures the running time of the
356wrapped function. A `PerformanceObserver` must be subscribed to the `'function'`
357event type in order for the timing details to be accessed.
358
359```js
360const {
361  performance,
362  PerformanceObserver,
363} = require('node:perf_hooks');
364
365function someFunction() {
366  console.log('hello world');
367}
368
369const wrapped = performance.timerify(someFunction);
370
371const obs = new PerformanceObserver((list) => {
372  console.log(list.getEntries()[0].duration);
373
374  performance.clearMarks();
375  performance.clearMeasures();
376  obs.disconnect();
377});
378obs.observe({ entryTypes: ['function'] });
379
380// A performance timeline entry will be created
381wrapped();
382```
383
384If the wrapped function returns a promise, a finally handler will be attached
385to the promise and the duration will be reported once the finally handler is
386invoked.
387
388### `performance.toJSON()`
389
390<!-- YAML
391added: v16.1.0
392-->
393
394An object which is JSON representation of the `performance` object. It
395is similar to [`window.performance.toJSON`][] in browsers.
396
397#### Event: `'resourcetimingbufferfull'`
398
399<!-- YAML
400added: v18.8.0
401-->
402
403The `'resourcetimingbufferfull'` event is fired when the global performance
404resource timing buffer is full. Adjust resource timing buffer size with
405`performance.setResourceTimingBufferSize()` or clear the buffer with
406`performance.clearResourceTimings()` in the event listener to allow
407more entries to be added to the performance timeline buffer.
408
409## Class: `PerformanceEntry`
410
411<!-- YAML
412added: v8.5.0
413-->
414
415### `performanceEntry.detail`
416
417<!-- YAML
418added: v16.0.0
419-->
420
421* {any}
422
423Additional detail specific to the `entryType`.
424
425### `performanceEntry.duration`
426
427<!-- YAML
428added: v8.5.0
429-->
430
431* {number}
432
433The total number of milliseconds elapsed for this entry. This value will not
434be meaningful for all Performance Entry types.
435
436### `performanceEntry.entryType`
437
438<!-- YAML
439added: v8.5.0
440-->
441
442* {string}
443
444The type of the performance entry. It may be one of:
445
446* `'node'` (Node.js only)
447* `'mark'` (available on the Web)
448* `'measure'` (available on the Web)
449* `'gc'` (Node.js only)
450* `'function'` (Node.js only)
451* `'http2'` (Node.js only)
452* `'http'` (Node.js only)
453
454### `performanceEntry.flags`
455
456<!-- YAML
457added:
458 - v13.9.0
459 - v12.17.0
460changes:
461  - version: v16.0.0
462    pr-url: https://github.com/nodejs/node/pull/37136
463    description: Runtime deprecated. Now moved to the detail property
464                 when entryType is 'gc'.
465-->
466
467* {number}
468
469_This property is an extension by Node.js. It is not available in Web browsers._
470
471When `performanceEntry.entryType` is equal to `'gc'`, the `performance.flags`
472property contains additional information about garbage collection operation.
473The value may be one of:
474
475* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_NO`
476* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED`
477* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_FORCED`
478* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING`
479* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE`
480* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY`
481* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE`
482
483### `performanceEntry.name`
484
485<!-- YAML
486added: v8.5.0
487-->
488
489* {string}
490
491The name of the performance entry.
492
493### `performanceEntry.kind`
494
495<!-- YAML
496added: v8.5.0
497changes:
498  - version: v16.0.0
499    pr-url: https://github.com/nodejs/node/pull/37136
500    description: Runtime deprecated. Now moved to the detail property
501                 when entryType is 'gc'.
502-->
503
504* {number}
505
506_This property is an extension by Node.js. It is not available in Web browsers._
507
508When `performanceEntry.entryType` is equal to `'gc'`, the `performance.kind`
509property identifies the type of garbage collection operation that occurred.
510The value may be one of:
511
512* `perf_hooks.constants.NODE_PERFORMANCE_GC_MAJOR`
513* `perf_hooks.constants.NODE_PERFORMANCE_GC_MINOR`
514* `perf_hooks.constants.NODE_PERFORMANCE_GC_INCREMENTAL`
515* `perf_hooks.constants.NODE_PERFORMANCE_GC_WEAKCB`
516
517### `performanceEntry.startTime`
518
519<!-- YAML
520added: v8.5.0
521-->
522
523* {number}
524
525The high resolution millisecond timestamp marking the starting time of the
526Performance Entry.
527
528### Garbage Collection ('gc') Details
529
530When `performanceEntry.type` is equal to `'gc'`, the `performanceEntry.detail`
531property will be an {Object} with two properties:
532
533* `kind` {number} One of:
534  * `perf_hooks.constants.NODE_PERFORMANCE_GC_MAJOR`
535  * `perf_hooks.constants.NODE_PERFORMANCE_GC_MINOR`
536  * `perf_hooks.constants.NODE_PERFORMANCE_GC_INCREMENTAL`
537  * `perf_hooks.constants.NODE_PERFORMANCE_GC_WEAKCB`
538* `flags` {number} One of:
539  * `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_NO`
540  * `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED`
541  * `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_FORCED`
542  * `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING`
543  * `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE`
544  * `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY`
545  * `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE`
546
547### HTTP ('http') Details
548
549When `performanceEntry.type` is equal to `'http'`, the `performanceEntry.detail`
550property will be an {Object} containing additional information.
551
552If `performanceEntry.name` is equal to `HttpClient`, the `detail`
553will contain the following properties: `req`, `res`. And the `req` property
554will be an {Object} containing `method`, `url`, `headers`, the `res` property
555will be an {Object} containing `statusCode`, `statusMessage`, `headers`.
556
557If `performanceEntry.name` is equal to `HttpRequest`, the `detail`
558will contain the following properties: `req`, `res`. And the `req` property
559will be an {Object} containing `method`, `url`, `headers`, the `res` property
560will be an {Object} containing `statusCode`, `statusMessage`, `headers`.
561
562This could add additional memory overhead and should only be used for
563diagnostic purposes, not left turned on in production by default.
564
565### HTTP/2 ('http2') Details
566
567When `performanceEntry.type` is equal to `'http2'`, the
568`performanceEntry.detail` property will be an {Object} containing
569additional performance information.
570
571If `performanceEntry.name` is equal to `Http2Stream`, the `detail`
572will contain the following properties:
573
574* `bytesRead` {number} The number of `DATA` frame bytes received for this
575  `Http2Stream`.
576* `bytesWritten` {number} The number of `DATA` frame bytes sent for this
577  `Http2Stream`.
578* `id` {number} The identifier of the associated `Http2Stream`
579* `timeToFirstByte` {number} The number of milliseconds elapsed between the
580  `PerformanceEntry` `startTime` and the reception of the first `DATA` frame.
581* `timeToFirstByteSent` {number} The number of milliseconds elapsed between
582  the `PerformanceEntry` `startTime` and sending of the first `DATA` frame.
583* `timeToFirstHeader` {number} The number of milliseconds elapsed between the
584  `PerformanceEntry` `startTime` and the reception of the first header.
585
586If `performanceEntry.name` is equal to `Http2Session`, the `detail` will
587contain the following properties:
588
589* `bytesRead` {number} The number of bytes received for this `Http2Session`.
590* `bytesWritten` {number} The number of bytes sent for this `Http2Session`.
591* `framesReceived` {number} The number of HTTP/2 frames received by the
592  `Http2Session`.
593* `framesSent` {number} The number of HTTP/2 frames sent by the `Http2Session`.
594* `maxConcurrentStreams` {number} The maximum number of streams concurrently
595  open during the lifetime of the `Http2Session`.
596* `pingRTT` {number} The number of milliseconds elapsed since the transmission
597  of a `PING` frame and the reception of its acknowledgment. Only present if
598  a `PING` frame has been sent on the `Http2Session`.
599* `streamAverageDuration` {number} The average duration (in milliseconds) for
600  all `Http2Stream` instances.
601* `streamCount` {number} The number of `Http2Stream` instances processed by
602  the `Http2Session`.
603* `type` {string} Either `'server'` or `'client'` to identify the type of
604  `Http2Session`.
605
606### Timerify ('function') Details
607
608When `performanceEntry.type` is equal to `'function'`, the
609`performanceEntry.detail` property will be an {Array} listing
610the input arguments to the timed function.
611
612### Net ('net') Details
613
614When `performanceEntry.type` is equal to `'net'`, the
615`performanceEntry.detail` property will be an {Object} containing
616additional information.
617
618If `performanceEntry.name` is equal to `connect`, the `detail`
619will contain the following properties: `host`, `port`.
620
621### DNS ('dns') Details
622
623When `performanceEntry.type` is equal to `'dns'`, the
624`performanceEntry.detail` property will be an {Object} containing
625additional information.
626
627If `performanceEntry.name` is equal to `lookup`, the `detail`
628will contain the following properties: `hostname`, `family`, `hints`, `verbatim`,
629`addresses`.
630
631If `performanceEntry.name` is equal to `lookupService`, the `detail` will
632contain the following properties: `host`, `port`, `hostname`, `service`.
633
634If `performanceEntry.name` is equal to `queryxxx` or `getHostByAddr`, the `detail` will
635contain the following properties: `host`, `ttl`, `result`. The value of `result` is
636same as the result of `queryxxx` or `getHostByAddr`.
637
638## Class: `PerformanceNodeTiming`
639
640<!-- YAML
641added: v8.5.0
642-->
643
644* Extends: {PerformanceEntry}
645
646_This property is an extension by Node.js. It is not available in Web browsers._
647
648Provides timing details for Node.js itself. The constructor of this class
649is not exposed to users.
650
651### `performanceNodeTiming.bootstrapComplete`
652
653<!-- YAML
654added: v8.5.0
655-->
656
657* {number}
658
659The high resolution millisecond timestamp at which the Node.js process
660completed bootstrapping. If bootstrapping has not yet finished, the property
661has the value of -1.
662
663### `performanceNodeTiming.environment`
664
665<!-- YAML
666added: v8.5.0
667-->
668
669* {number}
670
671The high resolution millisecond timestamp at which the Node.js environment was
672initialized.
673
674### `performanceNodeTiming.idleTime`
675
676<!-- YAML
677added:
678  - v14.10.0
679  - v12.19.0
680-->
681
682* {number}
683
684The high resolution millisecond timestamp of the amount of time the event loop
685has been idle within the event loop's event provider (e.g. `epoll_wait`). This
686does not take CPU usage into consideration. If the event loop has not yet
687started (e.g., in the first tick of the main script), the property has the
688value of 0.
689
690### `performanceNodeTiming.loopExit`
691
692<!-- YAML
693added: v8.5.0
694-->
695
696* {number}
697
698The high resolution millisecond timestamp at which the Node.js event loop
699exited. If the event loop has not yet exited, the property has the value of -1.
700It can only have a value of not -1 in a handler of the [`'exit'`][] event.
701
702### `performanceNodeTiming.loopStart`
703
704<!-- YAML
705added: v8.5.0
706-->
707
708* {number}
709
710The high resolution millisecond timestamp at which the Node.js event loop
711started. If the event loop has not yet started (e.g., in the first tick of the
712main script), the property has the value of -1.
713
714### `performanceNodeTiming.nodeStart`
715
716<!-- YAML
717added: v8.5.0
718-->
719
720* {number}
721
722The high resolution millisecond timestamp at which the Node.js process was
723initialized.
724
725### `performanceNodeTiming.v8Start`
726
727<!-- YAML
728added: v8.5.0
729-->
730
731* {number}
732
733The high resolution millisecond timestamp at which the V8 platform was
734initialized.
735
736## Class: `PerformanceResourceTiming`
737
738<!-- YAML
739added: v18.2.0
740-->
741
742* Extends: {PerformanceEntry}
743
744Provides detailed network timing data regarding the loading of an application's
745resources.
746
747The constructor of this class is not exposed to users directly.
748
749### `performanceResourceTiming.workerStart`
750
751<!-- YAML
752added: v18.2.0
753-->
754
755* {number}
756
757The high resolution millisecond timestamp at immediately before dispatching
758the `fetch` request. If the resource is not intercepted by a worker the property
759will always return 0.
760
761### `performanceResourceTiming.redirectStart`
762
763<!-- YAML
764added: v18.2.0
765-->
766
767* {number}
768
769The high resolution millisecond timestamp that represents the start time
770of the fetch which initiates the redirect.
771
772### `performanceResourceTiming.redirectEnd`
773
774<!-- YAML
775added: v18.2.0
776-->
777
778* {number}
779
780The high resolution millisecond timestamp that will be created immediately after
781receiving the last byte of the response of the last redirect.
782
783### `performanceResourceTiming.fetchStart`
784
785<!-- YAML
786added: v18.2.0
787-->
788
789* {number}
790
791The high resolution millisecond timestamp immediately before the Node.js starts
792to fetch the resource.
793
794### `performanceResourceTiming.domainLookupStart`
795
796<!-- YAML
797added: v18.2.0
798-->
799
800* {number}
801
802The high resolution millisecond timestamp immediately before the Node.js starts
803the domain name lookup for the resource.
804
805### `performanceResourceTiming.domainLookupEnd`
806
807<!-- YAML
808added: v18.2.0
809-->
810
811* {number}
812
813The high resolution millisecond timestamp representing the time immediately
814after the Node.js finished the domain name lookup for the resource.
815
816### `performanceResourceTiming.connectStart`
817
818<!-- YAML
819added: v18.2.0
820-->
821
822* {number}
823
824The high resolution millisecond timestamp representing the time immediately
825before Node.js starts to establish the connection to the server to retrieve
826the resource.
827
828### `performanceResourceTiming.connectEnd`
829
830<!-- YAML
831added: v18.2.0
832-->
833
834* {number}
835
836The high resolution millisecond timestamp representing the time immediately
837after Node.js finishes establishing the connection to the server to retrieve
838the resource.
839
840### `performanceResourceTiming.secureConnectionStart`
841
842<!-- YAML
843added: v18.2.0
844-->
845
846* {number}
847
848The high resolution millisecond timestamp representing the time immediately
849before Node.js starts the handshake process to secure the current connection.
850
851### `performanceResourceTiming.requestStart`
852
853<!-- YAML
854added: v18.2.0
855-->
856
857* {number}
858
859The high resolution millisecond timestamp representing the time immediately
860before Node.js receives the first byte of the response from the server.
861
862### `performanceResourceTiming.responseEnd`
863
864<!-- YAML
865added: v18.2.0
866-->
867
868* {number}
869
870The high resolution millisecond timestamp representing the time immediately
871after Node.js receives the last byte of the resource or immediately before
872the transport connection is closed, whichever comes first.
873
874### `performanceResourceTiming.transferSize`
875
876<!-- YAML
877added: v18.2.0
878-->
879
880* {number}
881
882A number representing the size (in octets) of the fetched resource. The size
883includes the response header fields plus the response payload body.
884
885### `performanceResourceTiming.encodedBodySize`
886
887<!-- YAML
888added: v18.2.0
889-->
890
891* {number}
892
893A number representing the size (in octets) received from the fetch
894(HTTP or cache), of the payload body, before removing any applied
895content-codings.
896
897### `performanceResourceTiming.decodedBodySize`
898
899<!-- YAML
900added: v18.2.0
901-->
902
903* {number}
904
905A number representing the size (in octets) received from the fetch
906(HTTP or cache), of the message body, after removing any applied
907content-codings.
908
909### `performanceResourceTiming.toJSON()`
910
911<!-- YAML
912added: v18.2.0
913-->
914
915Returns a `object` that is the JSON representation of the
916`PerformanceResourceTiming` object
917
918## Class: `perf_hooks.PerformanceObserver`
919
920<!-- YAML
921added: v8.5.0
922-->
923
924### `PerformanceObserver.supportedEntryTypes`
925
926<!-- YAML
927added: v16.0.0
928-->
929
930* {string\[]}
931
932Get supported types.
933
934### `new PerformanceObserver(callback)`
935
936<!-- YAML
937added: v8.5.0
938changes:
939  - version: v18.0.0
940    pr-url: https://github.com/nodejs/node/pull/41678
941    description: Passing an invalid callback to the `callback` argument
942                 now throws `ERR_INVALID_ARG_TYPE` instead of
943                 `ERR_INVALID_CALLBACK`.
944-->
945
946* `callback` {Function}
947  * `list` {PerformanceObserverEntryList}
948  * `observer` {PerformanceObserver}
949
950`PerformanceObserver` objects provide notifications when new
951`PerformanceEntry` instances have been added to the Performance Timeline.
952
953```js
954const {
955  performance,
956  PerformanceObserver,
957} = require('node:perf_hooks');
958
959const obs = new PerformanceObserver((list, observer) => {
960  console.log(list.getEntries());
961
962  performance.clearMarks();
963  performance.clearMeasures();
964  observer.disconnect();
965});
966obs.observe({ entryTypes: ['mark'], buffered: true });
967
968performance.mark('test');
969```
970
971Because `PerformanceObserver` instances introduce their own additional
972performance overhead, instances should not be left subscribed to notifications
973indefinitely. Users should disconnect observers as soon as they are no
974longer needed.
975
976The `callback` is invoked when a `PerformanceObserver` is
977notified about new `PerformanceEntry` instances. The callback receives a
978`PerformanceObserverEntryList` instance and a reference to the
979`PerformanceObserver`.
980
981### `performanceObserver.disconnect()`
982
983<!-- YAML
984added: v8.5.0
985-->
986
987Disconnects the `PerformanceObserver` instance from all notifications.
988
989### `performanceObserver.observe(options)`
990
991<!-- YAML
992added: v8.5.0
993changes:
994  - version: v16.7.0
995    pr-url: https://github.com/nodejs/node/pull/39297
996    description: Updated to conform to Performance Timeline Level 2. The
997                 buffered option has been added back.
998  - version: v16.0.0
999    pr-url: https://github.com/nodejs/node/pull/37136
1000    description: Updated to conform to User Timing Level 3. The
1001                 buffered option has been removed.
1002-->
1003
1004* `options` {Object}
1005  * `type` {string} A single {PerformanceEntry} type. Must not be given
1006    if `entryTypes` is already specified.
1007  * `entryTypes` {string\[]} An array of strings identifying the types of
1008    {PerformanceEntry} instances the observer is interested in. If not
1009    provided an error will be thrown.
1010  * `buffered` {boolean} If true, the observer callback is called with a
1011    list global `PerformanceEntry` buffered entries. If false, only
1012    `PerformanceEntry`s created after the time point are sent to the
1013    observer callback. **Default:** `false`.
1014
1015Subscribes the {PerformanceObserver} instance to notifications of new
1016{PerformanceEntry} instances identified either by `options.entryTypes`
1017or `options.type`:
1018
1019```js
1020const {
1021  performance,
1022  PerformanceObserver,
1023} = require('node:perf_hooks');
1024
1025const obs = new PerformanceObserver((list, observer) => {
1026  // Called once asynchronously. `list` contains three items.
1027});
1028obs.observe({ type: 'mark' });
1029
1030for (let n = 0; n < 3; n++)
1031  performance.mark(`test${n}`);
1032```
1033
1034## Class: `PerformanceObserverEntryList`
1035
1036<!-- YAML
1037added: v8.5.0
1038-->
1039
1040The `PerformanceObserverEntryList` class is used to provide access to the
1041`PerformanceEntry` instances passed to a `PerformanceObserver`.
1042The constructor of this class is not exposed to users.
1043
1044### `performanceObserverEntryList.getEntries()`
1045
1046<!-- YAML
1047added: v8.5.0
1048-->
1049
1050* Returns: {PerformanceEntry\[]}
1051
1052Returns a list of `PerformanceEntry` objects in chronological order
1053with respect to `performanceEntry.startTime`.
1054
1055```js
1056const {
1057  performance,
1058  PerformanceObserver,
1059} = require('node:perf_hooks');
1060
1061const obs = new PerformanceObserver((perfObserverList, observer) => {
1062  console.log(perfObserverList.getEntries());
1063  /**
1064   * [
1065   *   PerformanceEntry {
1066   *     name: 'test',
1067   *     entryType: 'mark',
1068   *     startTime: 81.465639,
1069   *     duration: 0
1070   *   },
1071   *   PerformanceEntry {
1072   *     name: 'meow',
1073   *     entryType: 'mark',
1074   *     startTime: 81.860064,
1075   *     duration: 0
1076   *   }
1077   * ]
1078   */
1079
1080  performance.clearMarks();
1081  performance.clearMeasures();
1082  observer.disconnect();
1083});
1084obs.observe({ type: 'mark' });
1085
1086performance.mark('test');
1087performance.mark('meow');
1088```
1089
1090### `performanceObserverEntryList.getEntriesByName(name[, type])`
1091
1092<!-- YAML
1093added: v8.5.0
1094-->
1095
1096* `name` {string}
1097* `type` {string}
1098* Returns: {PerformanceEntry\[]}
1099
1100Returns a list of `PerformanceEntry` objects in chronological order
1101with respect to `performanceEntry.startTime` whose `performanceEntry.name` is
1102equal to `name`, and optionally, whose `performanceEntry.entryType` is equal to
1103`type`.
1104
1105```js
1106const {
1107  performance,
1108  PerformanceObserver,
1109} = require('node:perf_hooks');
1110
1111const obs = new PerformanceObserver((perfObserverList, observer) => {
1112  console.log(perfObserverList.getEntriesByName('meow'));
1113  /**
1114   * [
1115   *   PerformanceEntry {
1116   *     name: 'meow',
1117   *     entryType: 'mark',
1118   *     startTime: 98.545991,
1119   *     duration: 0
1120   *   }
1121   * ]
1122   */
1123  console.log(perfObserverList.getEntriesByName('nope')); // []
1124
1125  console.log(perfObserverList.getEntriesByName('test', 'mark'));
1126  /**
1127   * [
1128   *   PerformanceEntry {
1129   *     name: 'test',
1130   *     entryType: 'mark',
1131   *     startTime: 63.518931,
1132   *     duration: 0
1133   *   }
1134   * ]
1135   */
1136  console.log(perfObserverList.getEntriesByName('test', 'measure')); // []
1137
1138  performance.clearMarks();
1139  performance.clearMeasures();
1140  observer.disconnect();
1141});
1142obs.observe({ entryTypes: ['mark', 'measure'] });
1143
1144performance.mark('test');
1145performance.mark('meow');
1146```
1147
1148### `performanceObserverEntryList.getEntriesByType(type)`
1149
1150<!-- YAML
1151added: v8.5.0
1152-->
1153
1154* `type` {string}
1155* Returns: {PerformanceEntry\[]}
1156
1157Returns a list of `PerformanceEntry` objects in chronological order
1158with respect to `performanceEntry.startTime` whose `performanceEntry.entryType`
1159is equal to `type`.
1160
1161```js
1162const {
1163  performance,
1164  PerformanceObserver,
1165} = require('node:perf_hooks');
1166
1167const obs = new PerformanceObserver((perfObserverList, observer) => {
1168  console.log(perfObserverList.getEntriesByType('mark'));
1169  /**
1170   * [
1171   *   PerformanceEntry {
1172   *     name: 'test',
1173   *     entryType: 'mark',
1174   *     startTime: 55.897834,
1175   *     duration: 0
1176   *   },
1177   *   PerformanceEntry {
1178   *     name: 'meow',
1179   *     entryType: 'mark',
1180   *     startTime: 56.350146,
1181   *     duration: 0
1182   *   }
1183   * ]
1184   */
1185  performance.clearMarks();
1186  performance.clearMeasures();
1187  observer.disconnect();
1188});
1189obs.observe({ type: 'mark' });
1190
1191performance.mark('test');
1192performance.mark('meow');
1193```
1194
1195## `perf_hooks.createHistogram([options])`
1196
1197<!-- YAML
1198added:
1199  - v15.9.0
1200  - v14.18.0
1201-->
1202
1203* `options` {Object}
1204  * `lowest` {number|bigint} The lowest discernible value. Must be an integer
1205    value greater than 0. **Default:** `1`.
1206  * `highest` {number|bigint} The highest recordable value. Must be an integer
1207    value that is equal to or greater than two times `lowest`.
1208    **Default:** `Number.MAX_SAFE_INTEGER`.
1209  * `figures` {number} The number of accuracy digits. Must be a number between
1210    `1` and `5`. **Default:** `3`.
1211* Returns {RecordableHistogram}
1212
1213Returns a {RecordableHistogram}.
1214
1215## `perf_hooks.monitorEventLoopDelay([options])`
1216
1217<!-- YAML
1218added: v11.10.0
1219-->
1220
1221* `options` {Object}
1222  * `resolution` {number} The sampling rate in milliseconds. Must be greater
1223    than zero. **Default:** `10`.
1224* Returns: {IntervalHistogram}
1225
1226_This property is an extension by Node.js. It is not available in Web browsers._
1227
1228Creates an `IntervalHistogram` object that samples and reports the event loop
1229delay over time. The delays will be reported in nanoseconds.
1230
1231Using a timer to detect approximate event loop delay works because the
1232execution of timers is tied specifically to the lifecycle of the libuv
1233event loop. That is, a delay in the loop will cause a delay in the execution
1234of the timer, and those delays are specifically what this API is intended to
1235detect.
1236
1237```js
1238const { monitorEventLoopDelay } = require('node:perf_hooks');
1239const h = monitorEventLoopDelay({ resolution: 20 });
1240h.enable();
1241// Do something.
1242h.disable();
1243console.log(h.min);
1244console.log(h.max);
1245console.log(h.mean);
1246console.log(h.stddev);
1247console.log(h.percentiles);
1248console.log(h.percentile(50));
1249console.log(h.percentile(99));
1250```
1251
1252## Class: `Histogram`
1253
1254<!-- YAML
1255added: v11.10.0
1256-->
1257
1258### `histogram.count`
1259
1260<!-- YAML
1261added:
1262  - v17.4.0
1263  - v16.14.0
1264-->
1265
1266* {number}
1267
1268The number of samples recorded by the histogram.
1269
1270### `histogram.countBigInt`
1271
1272<!-- YAML
1273added:
1274  - v17.4.0
1275  - v16.14.0
1276-->
1277
1278* {bigint}
1279
1280The number of samples recorded by the histogram.
1281
1282### `histogram.exceeds`
1283
1284<!-- YAML
1285added: v11.10.0
1286-->
1287
1288* {number}
1289
1290The number of times the event loop delay exceeded the maximum 1 hour event
1291loop delay threshold.
1292
1293### `histogram.exceedsBigInt`
1294
1295<!-- YAML
1296added:
1297  - v17.4.0
1298  - v16.14.0
1299-->
1300
1301* {bigint}
1302
1303The number of times the event loop delay exceeded the maximum 1 hour event
1304loop delay threshold.
1305
1306### `histogram.max`
1307
1308<!-- YAML
1309added: v11.10.0
1310-->
1311
1312* {number}
1313
1314The maximum recorded event loop delay.
1315
1316### `histogram.maxBigInt`
1317
1318<!-- YAML
1319added:
1320  - v17.4.0
1321  - v16.14.0
1322-->
1323
1324* {bigint}
1325
1326The maximum recorded event loop delay.
1327
1328### `histogram.mean`
1329
1330<!-- YAML
1331added: v11.10.0
1332-->
1333
1334* {number}
1335
1336The mean of the recorded event loop delays.
1337
1338### `histogram.min`
1339
1340<!-- YAML
1341added: v11.10.0
1342-->
1343
1344* {number}
1345
1346The minimum recorded event loop delay.
1347
1348### `histogram.minBigInt`
1349
1350<!-- YAML
1351added:
1352  - v17.4.0
1353  - v16.14.0
1354-->
1355
1356* {bigint}
1357
1358The minimum recorded event loop delay.
1359
1360### `histogram.percentile(percentile)`
1361
1362<!-- YAML
1363added: v11.10.0
1364-->
1365
1366* `percentile` {number} A percentile value in the range (0, 100].
1367* Returns: {number}
1368
1369Returns the value at the given percentile.
1370
1371### `histogram.percentileBigInt(percentile)`
1372
1373<!-- YAML
1374added:
1375  - v17.4.0
1376  - v16.14.0
1377-->
1378
1379* `percentile` {number} A percentile value in the range (0, 100].
1380* Returns: {bigint}
1381
1382Returns the value at the given percentile.
1383
1384### `histogram.percentiles`
1385
1386<!-- YAML
1387added: v11.10.0
1388-->
1389
1390* {Map}
1391
1392Returns a `Map` object detailing the accumulated percentile distribution.
1393
1394### `histogram.percentilesBigInt`
1395
1396<!-- YAML
1397added:
1398  - v17.4.0
1399  - v16.14.0
1400-->
1401
1402* {Map}
1403
1404Returns a `Map` object detailing the accumulated percentile distribution.
1405
1406### `histogram.reset()`
1407
1408<!-- YAML
1409added: v11.10.0
1410-->
1411
1412Resets the collected histogram data.
1413
1414### `histogram.stddev`
1415
1416<!-- YAML
1417added: v11.10.0
1418-->
1419
1420* {number}
1421
1422The standard deviation of the recorded event loop delays.
1423
1424## Class: `IntervalHistogram extends Histogram`
1425
1426A `Histogram` that is periodically updated on a given interval.
1427
1428### `histogram.disable()`
1429
1430<!-- YAML
1431added: v11.10.0
1432-->
1433
1434* Returns: {boolean}
1435
1436Disables the update interval timer. Returns `true` if the timer was
1437stopped, `false` if it was already stopped.
1438
1439### `histogram.enable()`
1440
1441<!-- YAML
1442added: v11.10.0
1443-->
1444
1445* Returns: {boolean}
1446
1447Enables the update interval timer. Returns `true` if the timer was
1448started, `false` if it was already started.
1449
1450### Cloning an `IntervalHistogram`
1451
1452{IntervalHistogram} instances can be cloned via {MessagePort}. On the receiving
1453end, the histogram is cloned as a plain {Histogram} object that does not
1454implement the `enable()` and `disable()` methods.
1455
1456## Class: `RecordableHistogram extends Histogram`
1457
1458<!-- YAML
1459added:
1460  - v15.9.0
1461  - v14.18.0
1462-->
1463
1464### `histogram.add(other)`
1465
1466<!-- YAML
1467added:
1468  - v17.4.0
1469  - v16.14.0
1470-->
1471
1472* `other` {RecordableHistogram}
1473
1474Adds the values from `other` to this histogram.
1475
1476### `histogram.record(val)`
1477
1478<!-- YAML
1479added:
1480  - v15.9.0
1481  - v14.18.0
1482-->
1483
1484* `val` {number|bigint} The amount to record in the histogram.
1485
1486### `histogram.recordDelta()`
1487
1488<!-- YAML
1489added:
1490  - v15.9.0
1491  - v14.18.0
1492-->
1493
1494Calculates the amount of time (in nanoseconds) that has passed since the
1495previous call to `recordDelta()` and records that amount in the histogram.
1496
1497## Examples
1498
1499### Measuring the duration of async operations
1500
1501The following example uses the [Async Hooks][] and Performance APIs to measure
1502the actual duration of a Timeout operation (including the amount of time it took
1503to execute the callback).
1504
1505```js
1506'use strict';
1507const async_hooks = require('node:async_hooks');
1508const {
1509  performance,
1510  PerformanceObserver,
1511} = require('node:perf_hooks');
1512
1513const set = new Set();
1514const hook = async_hooks.createHook({
1515  init(id, type) {
1516    if (type === 'Timeout') {
1517      performance.mark(`Timeout-${id}-Init`);
1518      set.add(id);
1519    }
1520  },
1521  destroy(id) {
1522    if (set.has(id)) {
1523      set.delete(id);
1524      performance.mark(`Timeout-${id}-Destroy`);
1525      performance.measure(`Timeout-${id}`,
1526                          `Timeout-${id}-Init`,
1527                          `Timeout-${id}-Destroy`);
1528    }
1529  },
1530});
1531hook.enable();
1532
1533const obs = new PerformanceObserver((list, observer) => {
1534  console.log(list.getEntries()[0]);
1535  performance.clearMarks();
1536  performance.clearMeasures();
1537  observer.disconnect();
1538});
1539obs.observe({ entryTypes: ['measure'], buffered: true });
1540
1541setTimeout(() => {}, 1000);
1542```
1543
1544### Measuring how long it takes to load dependencies
1545
1546The following example measures the duration of `require()` operations to load
1547dependencies:
1548
1549<!-- eslint-disable no-global-assign -->
1550
1551```js
1552'use strict';
1553const {
1554  performance,
1555  PerformanceObserver,
1556} = require('node:perf_hooks');
1557const mod = require('node:module');
1558
1559// Monkey patch the require function
1560mod.Module.prototype.require =
1561  performance.timerify(mod.Module.prototype.require);
1562require = performance.timerify(require);
1563
1564// Activate the observer
1565const obs = new PerformanceObserver((list) => {
1566  const entries = list.getEntries();
1567  entries.forEach((entry) => {
1568    console.log(`require('${entry[0]}')`, entry.duration);
1569  });
1570  performance.clearMarks();
1571  performance.clearMeasures();
1572  obs.disconnect();
1573});
1574obs.observe({ entryTypes: ['function'], buffered: true });
1575
1576require('some-module');
1577```
1578
1579### Measuring how long one HTTP round-trip takes
1580
1581The following example is used to trace the time spent by HTTP client
1582(`OutgoingMessage`) and HTTP request (`IncomingMessage`). For HTTP client,
1583it means the time interval between starting the request and receiving the
1584response, and for HTTP request, it means the time interval between receiving
1585the request and sending the response:
1586
1587```js
1588'use strict';
1589const { PerformanceObserver } = require('node:perf_hooks');
1590const http = require('node:http');
1591
1592const obs = new PerformanceObserver((items) => {
1593  items.getEntries().forEach((item) => {
1594    console.log(item);
1595  });
1596});
1597
1598obs.observe({ entryTypes: ['http'] });
1599
1600const PORT = 8080;
1601
1602http.createServer((req, res) => {
1603  res.end('ok');
1604}).listen(PORT, () => {
1605  http.get(`http://127.0.0.1:${PORT}`);
1606});
1607```
1608
1609### Measuring how long the `net.connect` (only for TCP) takes when the connection is successful
1610
1611```js
1612'use strict';
1613const { PerformanceObserver } = require('node:perf_hooks');
1614const net = require('node:net');
1615const obs = new PerformanceObserver((items) => {
1616  items.getEntries().forEach((item) => {
1617    console.log(item);
1618  });
1619});
1620obs.observe({ entryTypes: ['net'] });
1621const PORT = 8080;
1622net.createServer((socket) => {
1623  socket.destroy();
1624}).listen(PORT, () => {
1625  net.connect(PORT);
1626});
1627```
1628
1629### Measuring how long the DNS takes when the request is successful
1630
1631```js
1632'use strict';
1633const { PerformanceObserver } = require('node:perf_hooks');
1634const dns = require('node:dns');
1635const obs = new PerformanceObserver((items) => {
1636  items.getEntries().forEach((item) => {
1637    console.log(item);
1638  });
1639});
1640obs.observe({ entryTypes: ['dns'] });
1641dns.lookup('localhost', () => {});
1642dns.promises.resolve('localhost');
1643```
1644
1645[Async Hooks]: async_hooks.md
1646[Fetch Timing Info]: https://fetch.spec.whatwg.org/#fetch-timing-info
1647[High Resolution Time]: https://www.w3.org/TR/hr-time-2
1648[Performance Timeline]: https://w3c.github.io/performance-timeline/
1649[Resource Timing]: https://www.w3.org/TR/resource-timing-2/
1650[User Timing]: https://www.w3.org/TR/user-timing/
1651[Web Performance APIs]: https://w3c.github.io/perf-timing-primer/
1652[Worker threads]: worker_threads.md#worker-threads
1653[`'exit'`]: process.md#event-exit
1654[`child_process.spawnSync()`]: child_process.md#child_processspawnsynccommand-args-options
1655[`process.hrtime()`]: process.md#processhrtimetime
1656[`timeOrigin`]: https://w3c.github.io/hr-time/#dom-performance-timeorigin
1657[`window.performance.toJSON`]: https://developer.mozilla.org/en-US/docs/Web/API/Performance/toJSON
1658[`window.performance`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/performance
1659