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
|
||||
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`
|
||||
|
||||
<!-- YAML
|
||||
|
@ -28,6 +28,7 @@ const {
|
||||
NODE_PERFORMANCE_MILESTONE_ENVIRONMENT,
|
||||
},
|
||||
loopIdleTime,
|
||||
uvMetricsInfo,
|
||||
} = internalBinding('performance');
|
||||
|
||||
class PerformanceNodeTiming {
|
||||
@ -122,6 +123,13 @@ class PerformanceNodeTiming {
|
||||
configurable: true,
|
||||
get: loopIdleTime,
|
||||
},
|
||||
|
||||
uvMetricsInfo: {
|
||||
__proto__: null,
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
get: uvMetricsInfo,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -144,6 +144,8 @@
|
||||
V(env_var_settings_string, "envVarSettings") \
|
||||
V(errno_string, "errno") \
|
||||
V(error_string, "error") \
|
||||
V(events, "events") \
|
||||
V(events_waiting, "eventsWaiting") \
|
||||
V(exchange_string, "exchange") \
|
||||
V(expire_string, "expire") \
|
||||
V(exponent_string, "exponent") \
|
||||
@ -213,6 +215,7 @@
|
||||
V(kind_string, "kind") \
|
||||
V(length_string, "length") \
|
||||
V(library_string, "library") \
|
||||
V(loop_count, "loopCount") \
|
||||
V(mac_string, "mac") \
|
||||
V(max_buffer_string, "maxBuffer") \
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
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, "createELDHistogram", CreateELDHistogram);
|
||||
SetMethod(isolate, target, "markBootstrapComplete", MarkBootstrapComplete);
|
||||
SetMethod(isolate, target, "uvMetricsInfo", UvMetricsInfo);
|
||||
SetFastMethodNoSideEffect(
|
||||
isolate, target, "now", SlowPerformanceNow, &fast_performance_now);
|
||||
}
|
||||
@ -390,6 +415,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
|
||||
registry->Register(LoopIdleTime);
|
||||
registry->Register(CreateELDHistogram);
|
||||
registry->Register(MarkBootstrapComplete);
|
||||
registry->Register(UvMetricsInfo);
|
||||
registry->Register(SlowPerformanceNow);
|
||||
registry->Register(FastPerformanceNow);
|
||||
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