diff --git a/benchmark/worker/bench-eventlooputil.js b/benchmark/worker/bench-eventlooputil.js index 2d59f9f19ed563..9cfb592751a445 100644 --- a/benchmark/worker/bench-eventlooputil.js +++ b/benchmark/worker/bench-eventlooputil.js @@ -8,7 +8,7 @@ if (process.argv[2] === 'idle cats') { } const bench = common.createBenchmark(main, { - n: [1e6], + n: [1e7], method: [ 'ELU_simple', 'ELU_passed', diff --git a/lib/internal/perf/nodetiming.js b/lib/internal/perf/nodetiming.js index a9e0c3f252ce5e..d41fdc16f96b0f 100644 --- a/lib/internal/perf/nodetiming.js +++ b/lib/internal/perf/nodetiming.js @@ -164,6 +164,7 @@ class PerformanceNodeTiming { loopStart: this.loopStart, loopExit: this.loopExit, idleTime: this.idleTime, + uvMetricsInfo: this.uvMetricsInfo, }; } } diff --git a/src/node_external_reference.h b/src/node_external_reference.h index 5981e9db9c3bc4..7d27b7abdb7714 100644 --- a/src/node_external_reference.h +++ b/src/node_external_reference.h @@ -38,6 +38,10 @@ using CFunctionCallbackReturnInt32 = v8::FastApiCallbackOptions& options); using CFunctionCallbackValueReturnDouble = double (*)(v8::Local receiver); +using CFunctionCallbackValueReturnDoubleOptions = + double (*)(v8::Local, + // NOLINTNEXTLINE(runtime/references) This is V8 api. + v8::FastApiCallbackOptions&); using CFunctionCallbackValueReturnDoubleUnusedReceiver = double (*)(v8::Local unused, v8::Local receiver); using CFunctionCallbackWithInt64 = void (*)(v8::Local unused, @@ -111,6 +115,7 @@ class ExternalReferenceRegistry { V(CFunctionCallbackReturnInt32) \ V(CFunctionWithReturnUint32) \ V(CFunctionCallbackValueReturnDouble) \ + V(CFunctionCallbackValueReturnDoubleOptions) \ V(CFunctionCallbackValueReturnDoubleUnusedReceiver) \ V(CFunctionCallbackWithInt64) \ V(CFunctionCallbackWithBool) \ diff --git a/src/node_perf.cc b/src/node_perf.cc index d8b26f5c845be1..dd7881c4a90efe 100644 --- a/src/node_perf.cc +++ b/src/node_perf.cc @@ -4,6 +4,7 @@ #include "histogram-inl.h" #include "memory_tracker-inl.h" #include "node_buffer.h" +#include "node_debug.h" #include "node_external_reference.h" #include "node_internals.h" #include "node_process-inl.h" @@ -17,6 +18,7 @@ namespace performance { using v8::Array; using v8::Context; using v8::DontDelete; +using v8::FastApiCallbackOptions; using v8::Function; using v8::FunctionCallbackInfo; using v8::GCCallbackFlags; @@ -263,6 +265,17 @@ void LoopIdleTime(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(1.0 * idle_time / NANOS_PER_MILLIS); } +static double FastLoopIdleTime( + v8::Local receiver, + FastApiCallbackOptions& options) { // NOLINT(runtime/references) + TRACK_V8_FAST_API_CALL("performance.loopIdleTime"); + Environment* env = Environment::GetCurrent(options.isolate); + uint64_t idle_time = uv_metrics_idle_time(env->event_loop()); + return 1.0 * idle_time / NANOS_PER_MILLIS; +} + +static v8::CFunction fast_loop_idle_time(v8::CFunction::Make(FastLoopIdleTime)); + void UvMetricsInfo(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); Isolate* isolate = env->isolate(); @@ -338,7 +351,8 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data, "removeGarbageCollectionTracking", RemoveGarbageCollectionTracking); SetMethod(isolate, target, "notify", Notify); - SetMethod(isolate, target, "loopIdleTime", LoopIdleTime); + SetFastMethodNoSideEffect( + isolate, target, "loopIdleTime", LoopIdleTime, &fast_loop_idle_time); SetMethod(isolate, target, "createELDHistogram", CreateELDHistogram); SetMethod(isolate, target, "markBootstrapComplete", MarkBootstrapComplete); SetMethod(isolate, target, "uvMetricsInfo", UvMetricsInfo); @@ -406,6 +420,8 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(RemoveGarbageCollectionTracking); registry->Register(Notify); registry->Register(LoopIdleTime); + registry->Register(FastLoopIdleTime); + registry->Register(fast_loop_idle_time.GetTypeInfo()); registry->Register(CreateELDHistogram); registry->Register(MarkBootstrapComplete); registry->Register(UvMetricsInfo); diff --git a/test/parallel/test-perf-hooks-fast.js b/test/parallel/test-perf-hooks-fast.js new file mode 100644 index 00000000000000..d563e43a58c96b --- /dev/null +++ b/test/parallel/test-perf-hooks-fast.js @@ -0,0 +1,27 @@ +// Flags: --expose-internals --no-warnings --allow-natives-syntax +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { + performance +} = require('perf_hooks'); + +const { internalBinding } = require('internal/test/binding'); + +function testFastPerf() { + const obj = performance.eventLoopUtilization(); + assert.strictEqual(typeof obj.idle, 'number'); + assert.strictEqual(typeof obj.active, 'number'); + assert.strictEqual(typeof obj.utilization, 'number'); +} + +eval('%PrepareFunctionForOptimization(testFastPerf)'); +testFastPerf(); +eval('%OptimizeFunctionOnNextCall(testFastPerf)'); +testFastPerf(); + +if (common.isDebug) { + const { getV8FastApiCallCount } = internalBinding('debug'); + assert.strictEqual(getV8FastApiCallCount('performance.loopIdleTime'), 1); +}