Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf_hooks: add PerformanceResourceTiming #42725

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions benchmark/perf_hooks/resourcetiming.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
'use strict';

const common = require('../common.js');

const {
PerformanceObserver,
performance,
} = require('perf_hooks');

function createTimingInfo({
startTime = 0,
redirectStartTime = 0,
redirectEndTime = 0,
postRedirectStartTime = 0,
finalServiceWorkerStartTime = 0,
finalNetworkRequestStartTime = 0,
finalNetworkResponseStartTime = 0,
endTime = 0,
encodedBodySize = 0,
decodedBodySize = 0,
finalConnectionTimingInfo = null
}) {
if (finalConnectionTimingInfo !== null) {
finalConnectionTimingInfo.domainLookupStartTime =
finalConnectionTimingInfo.domainLookupStartTime || 0;
finalConnectionTimingInfo.domainLookupEndTime =
finalConnectionTimingInfo.domainLookupEndTime || 0;
finalConnectionTimingInfo.connectionStartTime =
finalConnectionTimingInfo.connectionStartTime || 0;
finalConnectionTimingInfo.connectionEndTime =
finalConnectionTimingInfo.connectionEndTime || 0;
finalConnectionTimingInfo.secureConnectionStartTime =
finalConnectionTimingInfo.secureConnectionStartTime || 0;
finalConnectionTimingInfo.ALPNNegotiatedProtocol =
finalConnectionTimingInfo.ALPNNegotiatedProtocol || [];
}
return {
startTime,
redirectStartTime,
redirectEndTime,
postRedirectStartTime,
finalServiceWorkerStartTime,
finalNetworkRequestStartTime,
finalNetworkResponseStartTime,
endTime,
encodedBodySize,
decodedBodySize,
finalConnectionTimingInfo,
};
}

const bench = common.createBenchmark(main, {
n: [1e5],
observe: ['resource'],
});

function test() {
const timingInfo = createTimingInfo({ finalConnectionTimingInfo: {} });
performance.markResourceTiming(
timingInfo,
'http://localhost:8080',
'fetch',
{},
''
);
}

function main({ n, observe }) {
const obs = new PerformanceObserver(() => {
bench.end(n);
});
obs.observe({ entryTypes: [observe], buffered: true });

bench.start();
for (let i = 0; i < 1e5; i++)
test();
}
223 changes: 223 additions & 0 deletions doc/api/perf_hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Node.js supports the following [Web Performance APIs][]:
* [High Resolution Time][]
* [Performance Timeline][]
* [User Timing][]
* [Resource Timing][]

```js
const { PerformanceObserver, performance } = require('node:perf_hooks');
Expand Down Expand Up @@ -66,6 +67,17 @@ added: v16.7.0
If `name` is not provided, removes all `PerformanceMeasure` objects from the
Performance Timeline. If `name` is provided, removes only the named mark.

### `performance.clearResourceTimings([name])`

<!-- YAML
added: REPLACEME
-->

* `name` {string}

If `name` is not provided, removes all `PerformanceResourceTiming` objects from
the Resource Timeline. If `name` is provided, removes only the named resource.

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

<!-- YAML
Expand Down Expand Up @@ -198,6 +210,33 @@ and can be queried with `performance.getEntries`,
observation is performed, the entries should be cleared from the global
Performance Timeline manually with `performance.clearMarks`.

### \`performance.markResourceTiming(timingInfo, requestedUrl, initiatorType,
RafaelGSS marked this conversation as resolved.
Show resolved Hide resolved

global, cacheMode)\`

<!-- YAML
added: REPLACEME
-->

* `timingInfo` {Object} [Fetch Timing Info][]
* `requestedUrl` {string} The resource url
* `initiatorType` {string} The initiator name, e.g: 'fetch'
* `global` {Object}
* `cacheMode` {string} The cache mode must be an empty string ('') or 'local'

_This property is an extension by Node.js. It is not available in Web browsers._

Creates a new `PerformanceResourceTiming` entry in the Resource Timeline. A
`PerformanceResourceTiming` is a subclass of `PerformanceEntry` whose
`performanceEntry.entryType` is always `'resource'`. Performance resources
are used to mark moments in the Resource Timeline.

The created `PerformanceMark` entry is put in the global Resource Timeline
and can be queried with `performance.getEntries`,
`performance.getEntriesByName`, and `performance.getEntriesByType`. When the
observation is performed, the entries should be cleared from the global
Performance Timeline manually with `performance.clearResourceTimings`.

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

<!-- YAML
Expand Down Expand Up @@ -653,6 +692,188 @@ added: v8.5.0
The high resolution millisecond timestamp at which the V8 platform was
initialized.

## Class: `PerformanceResourceTiming`

<!-- YAML
added: REPLACEME
-->

* Extends: {PerformanceEntry}

Provides detailed network timing data regarding the loading of an application's
resources.

The constructor of this class is not exposed to users directly.

### `performanceResourceTiming.workerStart`
RafaelGSS marked this conversation as resolved.
Show resolved Hide resolved

<!-- YAML
added: REPLACEME
-->

* {number}

The high resolution millisecond timestamp at immediately before dispatching
the `fetch` request. If the resource is not intercepted by a worker the property
will always return 0.

### `performanceResourceTiming.redirectStart`

<!-- YAML
added: REPLACEME
-->

* {number}

The high resolution millisecond timestamp that represents the start time
of the fetch which initiates the redirect.

### `performanceResourceTiming.redirectEnd`

<!-- YAML
added: REPLACEME
-->

* {number}

The high resolution millisecond timestamp that will be created immediately after
receiving the last byte of the response of the last redirect.

### `performanceResourceTiming.fetchStart`

<!-- YAML
added: REPLACEME
-->

* {number}

The high resolution millisecond timestamp immediately before the Node.js starts
to fetch the resource.

### `performanceResourceTiming.domainLookupStart`

<!-- YAML
added: REPLACEME
-->

* {number}

The high resolution millisecond timestamp immediately before the Node.js starts
the domain name lookup for the resource.

### `performanceResourceTiming.domainLookupEnd`

<!-- YAML
added: REPLACEME
-->

* {number}

The high resolution millisecond timestamp representing the time immediately
after the Node.js finished the domain name lookup for the resource.

### `performanceResourceTiming.connectStart`

<!-- YAML
added: REPLACEME
-->

* {number}

The high resolution millisecond timestamp representing the time immediately
before Node.js starts to establish the connection to the server to retrieve
the resource.

### `performanceResourceTiming.connectEnd`

<!-- YAML
added: REPLACEME
-->

* {number}

The high resolution millisecond timestamp representing the time immediately
after Node.js finishes establishing the connection to the server to retrieve
the resource.

### `performanceResourceTiming.secureConnectionStart`

<!-- YAML
added: REPLACEME
-->

* {number}

The high resolution millisecond timestamp representing the time immediately
before Node.js starts the handshake process to secure the current connection.

### `performanceResourceTiming.requestStart`

<!-- YAML
added: REPLACEME
-->

* {number}

The high resolution millisecond timestamp representing the time immediately
before Node.js receives the first byte of the response from the server.

### `performanceResourceTiming.responseEnd`

<!-- YAML
added: REPLACEME
-->

* {number}

The high resolution millisecond timestamp representing the time immediately
after Node.js receives the last byte of the resource or immediately before
the transport connection is closed, whichever comes first.

### `performanceResourceTiming.transferSize`

<!-- YAML
added: REPLACEME
-->

* {number}

A number representing the size (in octets) of the fetched resource. The size
includes the response header fields plus the response payload body.

### `performanceResourceTiming.encodedBodySize`

<!-- YAML
added: REPLACEME
-->

* {number}

A number representing the size (in octets) received from the fetch
(HTTP or cache), of the payload body, before removing any applied
content-codings.

### `performanceResourceTiming.decodedBodySize`

<!-- YAML
added: REPLACEME
-->

* {number}

A number representing the size (in octets) received from the fetch
(HTTP or cache), of the message body, after removing any applied
content-codings.

### `performanceResourceTiming.toJSON()`

<!-- YAML
added: REPLACEME
-->

Returns a `object` that is the JSON representation of the
`PerformanceResourceTiming` object

## Class: `perf_hooks.PerformanceObserver`

### `new PerformanceObserver(callback)`
Expand Down Expand Up @@ -1367,8 +1588,10 @@ dns.promises.resolve('localhost');
```

[Async Hooks]: async_hooks.md
[Fetch Timing Info]: https://fetch.spec.whatwg.org/#fetch-timing-info
[High Resolution Time]: https://www.w3.org/TR/hr-time-2
[Performance Timeline]: https://w3c.github.io/performance-timeline/
[Resource Timing]: https://www.w3.org/TR/resource-timing-2/
[User Timing]: https://www.w3.org/TR/user-timing/
[Web Performance APIs]: https://w3c.github.io/perf-timing-primer/
[Worker threads]: worker_threads.md#worker-threads
Expand Down
Loading