From 97af3d7da562406b75d1baeecb79ef8105d4b92a Mon Sep 17 00:00:00 2001 From: James M Snell Date: Thu, 17 Sep 2026 20:46:06 +0000 Subject: [PATCH] perf_hooks: add performanceNodeTiming.uvMetricsInfoBigInt `performance.nodeTiming.uvMetricsInfo` returns the libuv event loop metrics as numbers, which are only exact up to `Number.MAX_SAFE_INTEGER`. Add `uvMetricsInfoBigInt`, which returns the same metrics as bigints backed by `uint64_t` storage, carrying the full 64-bit range reported by libuv. A single native call fills both a `Float64Array` and a `BigUint64Array`, so `uvMetricsInfo` does not pay for bigint allocation and conversion. The new property is omitted from `toJSON()`, as `JSON.stringify()` cannot serialize bigints. Assisted-by: OpenCode Signed-off-by: James M Snell PR-URL: https://github.com/nodejs/node/pull/66094 Reviewed-By: Rafael Gonzaga Reviewed-By: Chengzhong Wu --- .../perf_hooks/nodetiming-uvmetricsinfo.js | 19 ++++++--- doc/api/perf_hooks.md | 41 +++++++++++++++++++ lib/internal/perf/nodetiming.js | 20 +++++++++ src/aliased_buffer.h | 3 +- src/node_perf.cc | 36 ++++++++++++---- src/node_perf_common.h | 5 ++- src/node_snapshotable.cc | 3 ++ .../fixtures/test-nodetiming-uvmetricsinfo.js | 28 ++++++++++++- ...ormance-nodetiming-uvmetricsinfo-buffer.js | 14 +++++-- ...ormance-nodetiming-uvmetricsinfo-worker.js | 26 ++++++++++++ test/parallel/test-performance-nodetiming.js | 20 +++++++++ typings/internalBinding/performance.d.ts | 1 + 12 files changed, 197 insertions(+), 19 deletions(-) create mode 100644 test/parallel/test-performance-nodetiming-uvmetricsinfo-worker.js diff --git a/benchmark/perf_hooks/nodetiming-uvmetricsinfo.js b/benchmark/perf_hooks/nodetiming-uvmetricsinfo.js index 1d8d174de14..d646631f4e9 100644 --- a/benchmark/perf_hooks/nodetiming-uvmetricsinfo.js +++ b/benchmark/perf_hooks/nodetiming-uvmetricsinfo.js @@ -11,6 +11,7 @@ const { const bench = common.createBenchmark(main, { n: [1e6], events: [1, 1000, 10000], + api: ['number', 'bigint'], }); async function runEvents(events) { @@ -19,11 +20,19 @@ async function runEvents(events) { } } -async function main({ n, events }) { +async function main({ n, events, api }) { await runEvents(events); - bench.start(); - for (let i = 0; i < n; i++) { - assert.ok(performance.nodeTiming.uvMetricsInfo); + if (api === 'bigint') { + bench.start(); + for (let i = 0; i < n; i++) { + assert.ok(performance.nodeTiming.uvMetricsInfoBigInt); + } + bench.end(n); + } else { + bench.start(); + for (let i = 0; i < n; i++) { + assert.ok(performance.nodeTiming.uvMetricsInfo); + } + bench.end(n); } - bench.end(n); } diff --git a/doc/api/perf_hooks.md b/doc/api/perf_hooks.md index e044f578f4f..6b4ef8582a0 100644 --- a/doc/api/perf_hooks.md +++ b/doc/api/perf_hooks.md @@ -862,6 +862,10 @@ added: This is a wrapper to the `uv_metrics_info` function. It returns the current set of event loop metrics. +The values are exact up to `Number.MAX_SAFE_INTEGER`. Use +[`performanceNodeTiming.uvMetricsInfoBigInt`][] to obtain the full 64-bit +values reported by libuv. + It is recommended to use this property inside a function whose execution was scheduled using `setImmediate` to avoid collecting metrics before finishing all operations scheduled during the current loop iteration. @@ -882,6 +886,41 @@ setImmediate(() => { }); ``` +### `performanceNodeTiming.uvMetricsInfoBigInt` + + + +* Type: {Object} + * `loopCount` {bigint} Number of event loop iterations. + * `events` {bigint} Number of events that have been processed by the event handler. + * `eventsWaiting` {bigint} Number of events that were waiting to be processed when the event provider was called. + +The same as [`performanceNodeTiming.uvMetricsInfo`][], except that the values +are {bigint}s carrying the full 64-bit range reported by libuv. + +Because `JSON.stringify()` cannot serialize {bigint} values, this property is +not enumerable and is not included in the output of +`performanceNodeTiming.toJSON()`. Copies of `performance.nodeTiming` made by +spreading its enumerable properties, for example, remain serializable. + +```cjs +const { performance } = require('node:perf_hooks'); + +setImmediate(() => { + console.log(performance.nodeTiming.uvMetricsInfoBigInt); +}); +``` + +```mjs +import { performance } from 'node:perf_hooks'; + +setImmediate(() => { + console.log(performance.nodeTiming.uvMetricsInfoBigInt); +}); +``` + ### `performanceNodeTiming.v8Start`