mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
src,lib: add performance.uvMetricsInfo
This commit exposes a new API to the perf_hooks.performance module. This wraps uv_metrics_info into performance.uvMetricsInfo() function. PR-URL: https://github.com/nodejs/node/pull/54413 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
This commit is contained in:
parent
d2479fa020
commit
9a275e15c3
@ -887,6 +887,40 @@ added: v8.5.0
|
|||||||
The high resolution millisecond timestamp at which the Node.js process was
|
The high resolution millisecond timestamp at which the Node.js process was
|
||||||
initialized.
|
initialized.
|
||||||
|
|
||||||
|
### `performanceNodeTiming.uvMetricsInfo`
|
||||||
|
|
||||||
|
<!-- YAML
|
||||||
|
added: REPLACEME
|
||||||
|
-->
|
||||||
|
|
||||||
|
* Returns: {Object}
|
||||||
|
* `loopCount` {number} Number of event loop iterations.
|
||||||
|
* `events` {number} Number of events that have been processed by the event handler.
|
||||||
|
* `eventsWaiting` {number} Number of events that were waiting to be processed when the event provider was called.
|
||||||
|
|
||||||
|
This is a wrapper to the `uv_metrics_info` function.
|
||||||
|
It returns the current set of event loop metrics.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
```cjs
|
||||||
|
const { performance } = require('node:perf_hooks');
|
||||||
|
|
||||||
|
setImmediate(() => {
|
||||||
|
console.log(performance.nodeTiming.uvMetricsInfo);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```mjs
|
||||||
|
import { performance } from 'node:perf_hooks';
|
||||||
|
|
||||||
|
setImmediate(() => {
|
||||||
|
console.log(performance.nodeTiming.uvMetricsInfo);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
### `performanceNodeTiming.v8Start`
|
### `performanceNodeTiming.v8Start`
|
||||||
|
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
|
@ -28,6 +28,7 @@ const {
|
|||||||
NODE_PERFORMANCE_MILESTONE_ENVIRONMENT,
|
NODE_PERFORMANCE_MILESTONE_ENVIRONMENT,
|
||||||
},
|
},
|
||||||
loopIdleTime,
|
loopIdleTime,
|
||||||
|
uvMetricsInfo,
|
||||||
} = internalBinding('performance');
|
} = internalBinding('performance');
|
||||||
|
|
||||||
class PerformanceNodeTiming {
|
class PerformanceNodeTiming {
|
||||||
@ -122,6 +123,13 @@ class PerformanceNodeTiming {
|
|||||||
configurable: true,
|
configurable: true,
|
||||||
get: loopIdleTime,
|
get: loopIdleTime,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
uvMetricsInfo: {
|
||||||
|
__proto__: null,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
get: uvMetricsInfo,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +144,8 @@
|
|||||||
V(env_var_settings_string, "envVarSettings") \
|
V(env_var_settings_string, "envVarSettings") \
|
||||||
V(errno_string, "errno") \
|
V(errno_string, "errno") \
|
||||||
V(error_string, "error") \
|
V(error_string, "error") \
|
||||||
|
V(events, "events") \
|
||||||
|
V(events_waiting, "eventsWaiting") \
|
||||||
V(exchange_string, "exchange") \
|
V(exchange_string, "exchange") \
|
||||||
V(expire_string, "expire") \
|
V(expire_string, "expire") \
|
||||||
V(exponent_string, "exponent") \
|
V(exponent_string, "exponent") \
|
||||||
@ -213,6 +215,7 @@
|
|||||||
V(kind_string, "kind") \
|
V(kind_string, "kind") \
|
||||||
V(length_string, "length") \
|
V(length_string, "length") \
|
||||||
V(library_string, "library") \
|
V(library_string, "library") \
|
||||||
|
V(loop_count, "loopCount") \
|
||||||
V(mac_string, "mac") \
|
V(mac_string, "mac") \
|
||||||
V(max_buffer_string, "maxBuffer") \
|
V(max_buffer_string, "maxBuffer") \
|
||||||
V(max_concurrent_streams_string, "maxConcurrentStreams") \
|
V(max_concurrent_streams_string, "maxConcurrentStreams") \
|
||||||
|
@ -261,6 +261,30 @@ void LoopIdleTime(const FunctionCallbackInfo<Value>& args) {
|
|||||||
args.GetReturnValue().Set(1.0 * idle_time / NANOS_PER_MILLIS);
|
args.GetReturnValue().Set(1.0 * idle_time / NANOS_PER_MILLIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UvMetricsInfo(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
Environment* env = Environment::GetCurrent(args);
|
||||||
|
uv_metrics_t metrics;
|
||||||
|
|
||||||
|
// uv_metrics_info always return 0
|
||||||
|
CHECK_EQ(uv_metrics_info(env->event_loop(), &metrics), 0);
|
||||||
|
|
||||||
|
Local<Object> obj = Object::New(env->isolate());
|
||||||
|
obj->Set(env->context(),
|
||||||
|
env->loop_count(),
|
||||||
|
Integer::NewFromUnsigned(env->isolate(), metrics.loop_count))
|
||||||
|
.Check();
|
||||||
|
obj->Set(env->context(),
|
||||||
|
env->events(),
|
||||||
|
Integer::NewFromUnsigned(env->isolate(), metrics.events))
|
||||||
|
.Check();
|
||||||
|
obj->Set(env->context(),
|
||||||
|
env->events_waiting(),
|
||||||
|
Integer::NewFromUnsigned(env->isolate(), metrics.events_waiting))
|
||||||
|
.Check();
|
||||||
|
|
||||||
|
args.GetReturnValue().Set(obj);
|
||||||
|
}
|
||||||
|
|
||||||
void CreateELDHistogram(const FunctionCallbackInfo<Value>& args) {
|
void CreateELDHistogram(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
int64_t interval = args[0].As<Integer>()->Value();
|
int64_t interval = args[0].As<Integer>()->Value();
|
||||||
@ -324,6 +348,7 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data,
|
|||||||
SetMethod(isolate, target, "loopIdleTime", LoopIdleTime);
|
SetMethod(isolate, target, "loopIdleTime", LoopIdleTime);
|
||||||
SetMethod(isolate, target, "createELDHistogram", CreateELDHistogram);
|
SetMethod(isolate, target, "createELDHistogram", CreateELDHistogram);
|
||||||
SetMethod(isolate, target, "markBootstrapComplete", MarkBootstrapComplete);
|
SetMethod(isolate, target, "markBootstrapComplete", MarkBootstrapComplete);
|
||||||
|
SetMethod(isolate, target, "uvMetricsInfo", UvMetricsInfo);
|
||||||
SetFastMethodNoSideEffect(
|
SetFastMethodNoSideEffect(
|
||||||
isolate, target, "now", SlowPerformanceNow, &fast_performance_now);
|
isolate, target, "now", SlowPerformanceNow, &fast_performance_now);
|
||||||
}
|
}
|
||||||
@ -390,6 +415,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
|
|||||||
registry->Register(LoopIdleTime);
|
registry->Register(LoopIdleTime);
|
||||||
registry->Register(CreateELDHistogram);
|
registry->Register(CreateELDHistogram);
|
||||||
registry->Register(MarkBootstrapComplete);
|
registry->Register(MarkBootstrapComplete);
|
||||||
|
registry->Register(UvMetricsInfo);
|
||||||
registry->Register(SlowPerformanceNow);
|
registry->Register(SlowPerformanceNow);
|
||||||
registry->Register(FastPerformanceNow);
|
registry->Register(FastPerformanceNow);
|
||||||
registry->Register(fast_performance_now.GetTypeInfo());
|
registry->Register(fast_performance_now.GetTypeInfo());
|
||||||
|
46
test/fixtures/test-nodetiming-uvmetricsinfo.js
vendored
Normal file
46
test/fixtures/test-nodetiming-uvmetricsinfo.js
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Enforcing strict checks on the order or number of events across different
|
||||||
|
// platforms can be tricky and unreliable due to various factors.
|
||||||
|
// As a result, this test relies on the `uv_metrics_info` call instead.
|
||||||
|
const { performance } = require('node:perf_hooks');
|
||||||
|
const assert = require('node:assert');
|
||||||
|
const fs = require('node:fs');
|
||||||
|
const { nodeTiming } = performance;
|
||||||
|
|
||||||
|
function safeMetricsInfo(cb) {
|
||||||
|
setImmediate(() => {
|
||||||
|
const info = nodeTiming.uvMetricsInfo;
|
||||||
|
cb(info);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const info = nodeTiming.uvMetricsInfo;
|
||||||
|
assert.strictEqual(info.loopCount, 0);
|
||||||
|
assert.strictEqual(info.events, 0);
|
||||||
|
// This is the only part of the test that we test events waiting
|
||||||
|
// Adding checks for this property will make the test flaky
|
||||||
|
// as it can be highly influenced by race conditions.
|
||||||
|
assert.strictEqual(info.eventsWaiting, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// The synchronous call should obviously not affect the uv metrics
|
||||||
|
const fd = fs.openSync(__filename, 'r');
|
||||||
|
fs.readFileSync(fd);
|
||||||
|
const info = nodeTiming.uvMetricsInfo;
|
||||||
|
assert.strictEqual(info.loopCount, 0);
|
||||||
|
assert.strictEqual(info.events, 0);
|
||||||
|
assert.strictEqual(info.eventsWaiting, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
function openFile(info) {
|
||||||
|
assert.strictEqual(info.loopCount, 1);
|
||||||
|
|
||||||
|
fs.open(__filename, 'r', (err) => {
|
||||||
|
assert.ifError(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
safeMetricsInfo(openFile);
|
||||||
|
}
|
20
test/parallel/test-performance-nodetiming-uvmetricsinfo.js
Normal file
20
test/parallel/test-performance-nodetiming-uvmetricsinfo.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
common.skipIfWorker();
|
||||||
|
|
||||||
|
const { spawnSync } = require('node:child_process');
|
||||||
|
const assert = require('node:assert');
|
||||||
|
const fixtures = require('../common/fixtures');
|
||||||
|
|
||||||
|
const file = fixtures.path('test-nodetiming-uvmetricsinfo.js');
|
||||||
|
|
||||||
|
{
|
||||||
|
const { status, stderr } = spawnSync(
|
||||||
|
process.execPath,
|
||||||
|
[
|
||||||
|
file,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
assert.strictEqual(status, 0, stderr.toString());
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user