GeezerVison is showing github.com — src,lib: add performance.uvMetricsInfo · nodejs/node@9ba75fa
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/perf_hooks.md +34Lines changed: 34 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -887,6 +887,40 @@ added: v8.5.0 | 887 | 887 | The high resolution millisecond timestamp at which the Node.js process was | 888 | 888 | initialized. | 889 | 889 |
| | 890 | +### `performanceNodeTiming.uvMetricsInfo` | | 891 | + | | 892 | +<!-- YAML | | 893 | +added: REPLACEME | | 894 | +--> | | 895 | + | | 896 | +* Returns: {Object} | | 897 | + * `loopCount` {number} Number of event loop iterations. | | 898 | + * `events` {number} Number of events that have been processed by the event handler. | | 899 | + * `eventsWaiting` {number} Number of events that were waiting to be processed when the event provider was called. | | 900 | + | | 901 | +This is a wrapper to the `uv_metrics_info` function. | | 902 | +It returns the current set of event loop metrics. | | 903 | + | | 904 | +It is recommended to use this property inside a function whose execution was | | 905 | +scheduled using `setImmediate` to avoid collecting metrics before finishing all | | 906 | +operations scheduled during the current loop iteration. | | 907 | + | | 908 | +```cjs | | 909 | +const { performance } = require('node:perf_hooks'); | | 910 | + | | 911 | +setImmediate(() => { | | 912 | + console.log(performance.nodeTiming.uvMetricsInfo); | | 913 | +}); | | 914 | +``` | | 915 | + | | 916 | +```mjs | | 917 | +import { performance } from 'node:perf_hooks'; | | 918 | + | | 919 | +setImmediate(() => { | | 920 | + console.log(performance.nodeTiming.uvMetricsInfo); | | 921 | +}); | | 922 | +``` | | 923 | + | 890 | 924 | ### `performanceNodeTiming.v8Start` | 891 | 925 |
| 892 | 926 | <!-- YAML | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/perf/nodetiming.js +8Lines changed: 8 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -28,6 +28,7 @@ const { | 28 | 28 | NODE_PERFORMANCE_MILESTONE_ENVIRONMENT, | 29 | 29 | }, | 30 | 30 | loopIdleTime, | | 31 | + uvMetricsInfo, | 31 | 32 | } = internalBinding('performance'); | 32 | 33 |
| 33 | 34 | class PerformanceNodeTiming { | @@ -122,6 +123,13 @@ class PerformanceNodeTiming { | 122 | 123 | configurable: true, | 123 | 124 | get: loopIdleTime, | 124 | 125 | }, | | 126 | + | | 127 | + uvMetricsInfo: { | | 128 | + __proto__: null, | | 129 | + enumerable: true, | | 130 | + configurable: true, | | 131 | + get: uvMetricsInfo, | | 132 | + }, | 125 | 133 | }); | 126 | 134 | } | 127 | 135 |
| |
Collapse file Copy file name to clipboardExpand all lines: src/env_properties.h +3Lines changed: 3 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 144 | 144 | V(env_var_settings_string, "envVarSettings") \ | 145 | 145 | V(errno_string, "errno") \ | 146 | 146 | V(error_string, "error") \ | | 147 | + V(events, "events") \ | | 148 | + V(events_waiting, "eventsWaiting") \ | 147 | 149 | V(exchange_string, "exchange") \ | 148 | 150 | V(expire_string, "expire") \ | 149 | 151 | V(exponent_string, "exponent") \ | | 213 | 215 | V(kind_string, "kind") \ | 214 | 216 | V(length_string, "length") \ | 215 | 217 | V(library_string, "library") \ | | 218 | + V(loop_count, "loopCount") \ | 216 | 219 | V(mac_string, "mac") \ | 217 | 220 | V(max_buffer_string, "maxBuffer") \ | 218 | 221 | V(max_concurrent_streams_string, "maxConcurrentStreams") \ | |
Collapse file Copy file name to clipboardExpand all lines: src/node_perf.cc +26Lines changed: 26 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -261,6 +261,30 @@ void LoopIdleTime(const FunctionCallbackInfo<Value>& args) { | 261 | 261 | args.GetReturnValue().Set(1.0 * idle_time / NANOS_PER_MILLIS); | 262 | 262 | } | 263 | 263 |
| | 264 | +void UvMetricsInfo(const FunctionCallbackInfo<Value>& args) { | | 265 | + Environment* env = Environment::GetCurrent(args); | | 266 | + uv_metrics_t metrics; | | 267 | + | | 268 | + // uv_metrics_info always return 0 | | 269 | + CHECK_EQ(uv_metrics_info(env->event_loop(), &metrics), 0); | | 270 | + | | 271 | + Local<Object> obj = Object::New(env->isolate()); | | 272 | + obj->Set(env->context(), | | 273 | + env->loop_count(), | | 274 | + Integer::NewFromUnsigned(env->isolate(), metrics.loop_count)) | | 275 | + .Check(); | | 276 | + obj->Set(env->context(), | | 277 | + env->events(), | | 278 | + Integer::NewFromUnsigned(env->isolate(), metrics.events)) | | 279 | + .Check(); | | 280 | + obj->Set(env->context(), | | 281 | + env->events_waiting(), | | 282 | + Integer::NewFromUnsigned(env->isolate(), metrics.events_waiting)) | | 283 | + .Check(); | | 284 | + | | 285 | + args.GetReturnValue().Set(obj); | | 286 | +} | | 287 | + | 264 | 288 | void CreateELDHistogram(const FunctionCallbackInfo<Value>& args) { | 265 | 289 | Environment* env = Environment::GetCurrent(args); | 266 | 290 | int64_t interval = args[0].As<Integer>()->Value(); | @@ -324,6 +348,7 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data, | 324 | 348 | SetMethod(isolate, target, "loopIdleTime", LoopIdleTime); | 325 | 349 | SetMethod(isolate, target, "createELDHistogram", CreateELDHistogram); | 326 | 350 | SetMethod(isolate, target, "markBootstrapComplete", MarkBootstrapComplete); | | 351 | + SetMethod(isolate, target, "uvMetricsInfo", UvMetricsInfo); | 327 | 352 | SetFastMethodNoSideEffect( | 328 | 353 | isolate, target, "now", SlowPerformanceNow, &fast_performance_now); | 329 | 354 | } | @@ -390,6 +415,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { | 390 | 415 | registry->Register(LoopIdleTime); | 391 | 416 | registry->Register(CreateELDHistogram); | 392 | 417 | registry->Register(MarkBootstrapComplete); | | 418 | + registry->Register(UvMetricsInfo); | 393 | 419 | registry->Register(SlowPerformanceNow); | 394 | 420 | registry->Register(FastPerformanceNow); | 395 | 421 | registry->Register(fast_performance_now.GetTypeInfo()); | |
Collapse file Copy file name to clipboard +46Lines changed: 46 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +// Enforcing strict checks on the order or number of events across different | | 2 | +// platforms can be tricky and unreliable due to various factors. | | 3 | +// As a result, this test relies on the `uv_metrics_info` call instead. | | 4 | +const { performance } = require('node:perf_hooks'); | | 5 | +const assert = require('node:assert'); | | 6 | +const fs = require('node:fs'); | | 7 | +const { nodeTiming } = performance; | | 8 | + | | 9 | +function safeMetricsInfo(cb) { | | 10 | + setImmediate(() => { | | 11 | + const info = nodeTiming.uvMetricsInfo; | | 12 | + cb(info); | | 13 | + }); | | 14 | +} | | 15 | + | | 16 | +{ | | 17 | + const info = nodeTiming.uvMetricsInfo; | | 18 | + assert.strictEqual(info.loopCount, 0); | | 19 | + assert.strictEqual(info.events, 0); | | 20 | + // This is the only part of the test that we test events waiting | | 21 | + // Adding checks for this property will make the test flaky | | 22 | + // as it can be highly influenced by race conditions. | | 23 | + assert.strictEqual(info.eventsWaiting, 0); | | 24 | +} | | 25 | + | | 26 | +{ | | 27 | + // The synchronous call should obviously not affect the uv metrics | | 28 | + const fd = fs.openSync(__filename, 'r'); | | 29 | + fs.readFileSync(fd); | | 30 | + const info = nodeTiming.uvMetricsInfo; | | 31 | + assert.strictEqual(info.loopCount, 0); | | 32 | + assert.strictEqual(info.events, 0); | | 33 | + assert.strictEqual(info.eventsWaiting, 0); | | 34 | +} | | 35 | + | | 36 | +{ | | 37 | + function openFile(info) { | | 38 | + assert.strictEqual(info.loopCount, 1); | | 39 | + | | 40 | + fs.open(__filename, 'r', (err) => { | | 41 | + assert.ifError(err); | | 42 | + }); | | 43 | + } | | 44 | + | | 45 | + safeMetricsInfo(openFile); | | 46 | +} |
Collapse file Copy file name to clipboard +20Lines changed: 20 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | +common.skipIfWorker(); | | 5 | + | | 6 | +const { spawnSync } = require('node:child_process'); | | 7 | +const assert = require('node:assert'); | | 8 | +const fixtures = require('../common/fixtures'); | | 9 | + | | 10 | +const file = fixtures.path('test-nodetiming-uvmetricsinfo.js'); | | 11 | + | | 12 | +{ | | 13 | + const { status, stderr } = spawnSync( | | 14 | + process.execPath, | | 15 | + [ | | 16 | + file, | | 17 | + ], | | 18 | + ); | | 19 | + assert.strictEqual(status, 0, stderr.toString()); | | 20 | +} |
|