diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index 863d4ef5608bce..58f7396990dddb 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -241,10 +241,9 @@ if (!config.noBrowserGlobals) { defineOperation(globalThis, 'queueMicrotask', queueMicrotask); - defineLazyGlobal(globalThis, 'performance', () => { - const { performance } = require('perf_hooks'); - return performance; - }); + // https://www.w3.org/TR/hr-time-2/#the-performance-attribute + defineReplacableAttribute(globalThis, 'performance', + require('perf_hooks').performance); // Non-standard extensions: defineOperation(globalThis, 'clearImmediate', timers.clearImmediate); @@ -494,20 +493,12 @@ function defineOperation(target, name, method) { }); } -function defineLazyGlobal(target, name, loader) { - let value; - let overridden = false; +// https://heycam.github.io/webidl/#Replaceable +function defineReplacableAttribute(target, name, value) { ObjectDefineProperty(target, name, { + writable: true, enumerable: true, configurable: true, - get() { - if (value === undefined && !overridden) - value = loader(); - return value; - }, - set(val) { - value = val; - overridden = true; - } + value, }); } diff --git a/lib/internal/bootstrap/pre_execution.js b/lib/internal/bootstrap/pre_execution.js index 83ccfe90c11065..3b69844dc4ea0c 100644 --- a/lib/internal/bootstrap/pre_execution.js +++ b/lib/internal/bootstrap/pre_execution.js @@ -27,6 +27,7 @@ function prepareMainThreadExecution(expandArgv1 = false) { // Patch the process object with legacy properties and normalizations patchProcessObject(expandArgv1); setupTraceCategoryState(); + setupPerfHooks(); setupInspectorHooks(); setupWarningHandler(); @@ -222,6 +223,11 @@ function setupTraceCategoryState() { toggleTraceCategoryState(isTraceCategoryEnabled('node.async_hooks')); } +function setupPerfHooks() { + require('internal/perf/performance').refreshTimeOrigin(); + require('internal/perf/utils').refreshTimeOrigin(); +} + function setupInspectorHooks() { // If Debugger.setAsyncCallStackDepth is sent during bootstrap, // we cannot immediately call into JS to enable the hooks, which could @@ -474,6 +480,7 @@ module.exports = { setupCoverageHooks, setupWarningHandler, setupDebugEnv, + setupPerfHooks, prepareMainThreadExecution, initializeDeprecations, initializeESMLoader, diff --git a/lib/internal/event_target.js b/lib/internal/event_target.js index 026746825b7767..825e1e8b2597ab 100644 --- a/lib/internal/event_target.js +++ b/lib/internal/event_target.js @@ -59,13 +59,7 @@ const kRemoveListener = Symbol('kRemoveListener'); const kIsNodeStyleListener = Symbol('kIsNodeStyleListener'); const kTrustEvent = Symbol('kTrustEvent'); -// Lazy load perf_hooks to avoid the additional overhead on startup -let perf_hooks; -function lazyNow() { - if (perf_hooks === undefined) - perf_hooks = require('perf_hooks'); - return perf_hooks.performance.now(); -} +const { now } = require('internal/perf/utils'); // TODO(joyeecheung): V8 snapshot does not support instance member // initializers for now: @@ -98,7 +92,7 @@ class Event { this[kComposed] = !!composed; this[kType] = `${type}`; this[kDefaultPrevented] = false; - this[kTimestamp] = lazyNow(); + this[kTimestamp] = now(); this[kPropagationStopped] = false; if (options?.[kTrustEvent]) { isTrustedSet.add(this); diff --git a/lib/internal/http.js b/lib/internal/http.js index badfaa5c4a88d8..56187a2b1cc315 100644 --- a/lib/internal/http.js +++ b/lib/internal/http.js @@ -9,7 +9,7 @@ const { const { setUnrefTimeout } = require('internal/timers'); -const { InternalPerformanceEntry } = require('internal/perf/perf'); +const { InternalPerformanceEntry } = require('internal/perf/performance_entry'); const { enqueue, diff --git a/lib/internal/main/worker_thread.js b/lib/internal/main/worker_thread.js index e22fd17fa2d214..d6434ff96e1185 100644 --- a/lib/internal/main/worker_thread.js +++ b/lib/internal/main/worker_thread.js @@ -18,6 +18,7 @@ const { setupInspectorHooks, setupWarningHandler, setupDebugEnv, + setupPerfHooks, initializeDeprecations, initializeWASI, initializeCJSLoader, @@ -114,6 +115,7 @@ port.on('message', (message) => { } = message; setupTraceCategoryState(); + setupPerfHooks(); initializeReport(); if (manifestSrc) { require('internal/process/policy').setup(manifestSrc, manifestURL); diff --git a/lib/internal/perf/event_loop_utilization.js b/lib/internal/perf/event_loop_utilization.js index 398c4ad4e42f58..d73b2f5a831ab9 100644 --- a/lib/internal/perf/event_loop_utilization.js +++ b/lib/internal/perf/event_loop_utilization.js @@ -2,7 +2,7 @@ const nodeTiming = require('internal/perf/nodetiming'); -const { now } = require('internal/perf/perf'); +const { now } = require('internal/perf/utils'); function eventLoopUtilization(util1, util2) { const ls = nodeTiming.loopStart; diff --git a/lib/internal/perf/nodetiming.js b/lib/internal/perf/nodetiming.js index 5ff6dd38cd86d3..fcbd7efff49099 100644 --- a/lib/internal/perf/nodetiming.js +++ b/lib/internal/perf/nodetiming.js @@ -3,15 +3,14 @@ const { ObjectDefineProperties, ObjectSetPrototypeOf, - SafeArrayIterator, - SafeSet, } = primordials; +const { PerformanceEntry } = require('internal/perf/performance_entry'); + const { - PerformanceEntry, - kReadOnlyAttributes, now, -} = require('internal/perf/perf'); + getMilestoneTimestamp, +} = require('internal/perf/utils'); const { customInspectSymbol: kInspect, @@ -29,26 +28,8 @@ const { NODE_PERFORMANCE_MILESTONE_ENVIRONMENT }, loopIdleTime, - milestones, - timeOrigin, } = internalBinding('performance'); -function getMilestoneTimestamp(milestoneIdx) { - const ns = milestones[milestoneIdx]; - if (ns === -1) - return ns; - return ns / 1e6 - timeOrigin; -} - -const readOnlyAttributes = new SafeSet(new SafeArrayIterator([ - 'nodeStart', - 'v8Start', - 'environment', - 'loopStart', - 'loopExit', - 'bootstrapComplete', -])); - class PerformanceNodeTiming { constructor() { ObjectDefineProperties(this, { @@ -159,10 +140,6 @@ class PerformanceNodeTiming { idleTime: this.idleTime, }; } - - static get [kReadOnlyAttributes]() { - return readOnlyAttributes; - } } ObjectSetPrototypeOf( diff --git a/lib/internal/perf/observe.js b/lib/internal/perf/observe.js index c96925c723f64e..8ec8512434510b 100644 --- a/lib/internal/perf/observe.js +++ b/lib/internal/perf/observe.js @@ -31,7 +31,7 @@ const { const { InternalPerformanceEntry, isPerformanceEntry, -} = require('internal/perf/perf'); +} = require('internal/perf/performance_entry'); const { codes: { @@ -174,11 +174,13 @@ class PerformanceObserverEntryList { } class PerformanceObserver { - [kBuffer] = []; - [kEntryTypes] = new SafeSet(); - [kType] = undefined; - constructor(callback) { + // TODO(joyeecheung): V8 snapshot does not support instance member + // initializers for now: + // https://bugs.chromium.org/p/v8/issues/detail?id=10704 + this[kBuffer] = []; + this[kEntryTypes] = new SafeSet(); + this[kType] = undefined; validateCallback(callback); this[kCallback] = callback; } diff --git a/lib/internal/perf/performance.js b/lib/internal/perf/performance.js new file mode 100644 index 00000000000000..ca4aed90e4e270 --- /dev/null +++ b/lib/internal/perf/performance.js @@ -0,0 +1,129 @@ +'use strict'; + +const { + ObjectDefineProperty, + ObjectDefineProperties, + ObjectSetPrototypeOf, + TypeError, +} = primordials; + +const { + EventTarget, +} = require('internal/event_target'); + +const { now } = require('internal/perf/utils'); + +const { + mark, + measure, + clearMarks, +} = require('internal/perf/usertiming'); + +const eventLoopUtilization = require('internal/perf/event_loop_utilization'); +const nodeTiming = require('internal/perf/nodetiming'); +const timerify = require('internal/perf/timerify'); +const { customInspectSymbol: kInspect } = require('internal/util'); +const { inspect } = require('util'); + +const { + getTimeOriginTimestamp +} = internalBinding('performance'); + +class Performance extends EventTarget { + constructor() { + // eslint-disable-next-line no-restricted-syntax + throw new TypeError('Illegal constructor'); + } + + [kInspect](depth, options) { + if (depth < 0) return this; + + const opts = { + ...options, + depth: options.depth == null ? null : options.depth - 1 + }; + + return `Performance ${inspect({ + nodeTiming: this.nodeTiming, + timeOrigin: this.timeOrigin, + }, opts)}`; + } + +} + +function toJSON() { + return { + nodeTiming: this.nodeTiming, + timeOrigin: this.timeOrigin, + eventLoopUtilization: this.eventLoopUtilization() + }; +} + +class InternalPerformance extends EventTarget {} +InternalPerformance.prototype.constructor = Performance.prototype.constructor; +ObjectSetPrototypeOf(InternalPerformance.prototype, Performance.prototype); + +ObjectDefineProperties(Performance.prototype, { + clearMarks: { + configurable: true, + enumerable: false, + value: clearMarks, + }, + eventLoopUtilization: { + configurable: true, + enumerable: false, + value: eventLoopUtilization, + }, + mark: { + configurable: true, + enumerable: false, + value: mark, + }, + measure: { + configurable: true, + enumerable: false, + value: measure, + }, + nodeTiming: { + configurable: true, + enumerable: false, + value: nodeTiming, + }, + now: { + configurable: true, + enumerable: false, + value: now, + }, + timerify: { + configurable: true, + enumerable: false, + value: timerify, + }, + // This would be updated during pre-execution in case + // the process is launched from a snapshot. + // TODO(joyeecheung): we may want to warn about access to + // this during snapshot building. + timeOrigin: { + configurable: true, + enumerable: true, + value: getTimeOriginTimestamp(), + }, + toJSON: { + configurable: true, + enumerable: true, + value: toJSON, + } +}); + +function refreshTimeOrigin() { + ObjectDefineProperty(Performance.prototype, 'timeOrigin', { + configurable: true, + enumerable: true, + value: getTimeOriginTimestamp(), + }); +} + +module.exports = { + InternalPerformance, + refreshTimeOrigin +}; diff --git a/lib/internal/perf/perf.js b/lib/internal/perf/performance_entry.js similarity index 87% rename from lib/internal/perf/perf.js rename to lib/internal/perf/performance_entry.js index d049d3c68fff04..f9f1c9e8966e2d 100644 --- a/lib/internal/perf/perf.js +++ b/lib/internal/perf/performance_entry.js @@ -6,10 +6,6 @@ const { TypeError, } = primordials; -const { - timeOrigin, -} = internalBinding('performance'); - const { customInspectSymbol: kInspect, } = require('internal/util'); @@ -21,12 +17,6 @@ const kType = Symbol('kType'); const kStart = Symbol('kStart'); const kDuration = Symbol('kDuration'); const kDetail = Symbol('kDetail'); -const kReadOnlyAttributes = Symbol('kReadOnlyAttributes'); - -function now() { - const hr = process.hrtime(); - return (hr[0] * 1000 + hr[1] / 1e6) - timeOrigin; -} function isPerformanceEntry(obj) { return obj?.[kName] !== undefined; @@ -88,7 +78,5 @@ ObjectSetPrototypeOf( module.exports = { InternalPerformanceEntry, PerformanceEntry, - kReadOnlyAttributes, isPerformanceEntry, - now, }; diff --git a/lib/internal/perf/timerify.js b/lib/internal/perf/timerify.js index d730f62aae7eb1..dae0b06bf80c8a 100644 --- a/lib/internal/perf/timerify.js +++ b/lib/internal/perf/timerify.js @@ -9,10 +9,8 @@ const { Symbol, } = primordials; -const { - InternalPerformanceEntry, - now, -} = require('internal/perf/perf'); +const { InternalPerformanceEntry } = require('internal/perf/performance_entry'); +const { now } = require('internal/perf/utils'); const { validateFunction, diff --git a/lib/internal/perf/usertiming.js b/lib/internal/perf/usertiming.js index 6672a3f4dfdeb0..f83091de1919a8 100644 --- a/lib/internal/perf/usertiming.js +++ b/lib/internal/perf/usertiming.js @@ -3,16 +3,13 @@ const { ObjectKeys, SafeMap, + SafeSet, + SafeArrayIterator, } = primordials; -const { - InternalPerformanceEntry, - kReadOnlyAttributes, - now, -} = require('internal/perf/perf'); - +const { InternalPerformanceEntry } = require('internal/perf/performance_entry'); +const { now } = require('internal/perf/utils'); const { enqueue } = require('internal/perf/observe'); - const nodeTiming = require('internal/perf/nodetiming'); const { @@ -31,8 +28,15 @@ const { } = require('internal/errors'); const marks = new SafeMap(); -const nodeTimingReadOnlyAttributes = - nodeTiming.constructor[kReadOnlyAttributes]; + +const nodeTimingReadOnlyAttributes = new SafeSet(new SafeArrayIterator([ + 'nodeStart', + 'v8Start', + 'environment', + 'loopStart', + 'loopExit', + 'bootstrapComplete', +])); function getMark(name) { if (name === undefined) return; diff --git a/lib/internal/perf/utils.js b/lib/internal/perf/utils.js new file mode 100644 index 00000000000000..bcc7e223b8c882 --- /dev/null +++ b/lib/internal/perf/utils.js @@ -0,0 +1,33 @@ +'use strict'; + +const binding = internalBinding('performance'); +const { + milestones, + getTimeOrigin, +} = binding; + +// TODO(joyeecheung): we may want to warn about access to +// this during snapshot building. +let timeOrigin = getTimeOrigin(); + +function now() { + const hr = process.hrtime(); + return (hr[0] * 1000 + hr[1] / 1e6) - timeOrigin; +} + +function getMilestoneTimestamp(milestoneIdx) { + const ns = milestones[milestoneIdx]; + if (ns === -1) + return ns; + return ns / 1e6 - timeOrigin; +} + +function refreshTimeOrigin() { + timeOrigin = getTimeOrigin(); +} + +module.exports = { + now, + getMilestoneTimestamp, + refreshTimeOrigin +}; diff --git a/lib/internal/worker.js b/lib/internal/worker.js index f2414ebeec4aae..931bce0c518fc3 100644 --- a/lib/internal/worker.js +++ b/lib/internal/worker.js @@ -28,7 +28,7 @@ const { const EventEmitter = require('events'); const assert = require('internal/assert'); const path = require('path'); -const { timeOrigin } = internalBinding('performance'); +const { now } = require('internal/perf/utils'); const errorCodes = require('internal/errors').codes; const { @@ -504,12 +504,6 @@ function eventLoopUtilization(util1, util2) { return { idle: idle_delta, active: active_delta, utilization }; } -// Duplicate code from performance.now() so don't need to require perf_hooks. -function now() { - const hr = process.hrtime(); - return (hr[0] * 1000 + hr[1] / 1e6) - timeOrigin; -} - module.exports = { ownsProcessState, isMainThread, diff --git a/lib/perf_hooks.js b/lib/perf_hooks.js index a92a040f2de839..339d3ca4ff0ab4 100644 --- a/lib/perf_hooks.js +++ b/lib/perf_hooks.js @@ -1,126 +1,23 @@ 'use strict'; const { - ObjectDefineProperties, ObjectDefineProperty, - ObjectSetPrototypeOf, - TypeError, } = primordials; const { - timeOriginTimestamp, constants, } = internalBinding('performance'); -const { - EventTarget, -} = require('internal/event_target'); - -const { - PerformanceEntry, - now, -} = require('internal/perf/perf'); +const { PerformanceEntry } = require('internal/perf/performance_entry'); const { PerformanceObserver } = require('internal/perf/observe'); - -const { - PerformanceMark, - mark, - measure, - clearMarks, -} = require('internal/perf/usertiming'); +const { PerformanceMark } = require('internal/perf/usertiming'); +const { InternalPerformance } = require('internal/perf/performance'); const { createHistogram } = require('internal/histogram'); -const eventLoopUtilization = require('internal/perf/event_loop_utilization'); const monitorEventLoopDelay = require('internal/perf/event_loop_delay'); -const nodeTiming = require('internal/perf/nodetiming'); -const timerify = require('internal/perf/timerify'); -const { customInspectSymbol: kInspect } = require('internal/util'); -const { inspect } = require('util'); - -class Performance extends EventTarget { - constructor() { - // eslint-disable-next-line no-restricted-syntax - throw new TypeError('Illegal constructor'); - } - - [kInspect](depth, options) { - if (depth < 0) return this; - - const opts = { - ...options, - depth: options.depth == null ? null : options.depth - 1 - }; - - return `Performance ${inspect({ - nodeTiming: this.nodeTiming, - timeOrigin: this.timeOrigin, - }, opts)}`; - } - -} - -function toJSON() { - return { - nodeTiming: this.nodeTiming, - timeOrigin: this.timeOrigin, - eventLoopUtilization: this.eventLoopUtilization() - }; -} - -class InternalPerformance extends EventTarget {} -InternalPerformance.prototype.constructor = Performance.prototype.constructor; -ObjectSetPrototypeOf(InternalPerformance.prototype, Performance.prototype); - -ObjectDefineProperties(Performance.prototype, { - clearMarks: { - configurable: true, - enumerable: false, - value: clearMarks, - }, - eventLoopUtilization: { - configurable: true, - enumerable: false, - value: eventLoopUtilization, - }, - mark: { - configurable: true, - enumerable: false, - value: mark, - }, - measure: { - configurable: true, - enumerable: false, - value: measure, - }, - nodeTiming: { - configurable: true, - enumerable: false, - value: nodeTiming, - }, - now: { - configurable: true, - enumerable: false, - value: now, - }, - timerify: { - configurable: true, - enumerable: false, - value: timerify, - }, - timeOrigin: { - configurable: true, - enumerable: true, - value: timeOriginTimestamp, - }, - toJSON: { - configurable: true, - enumerable: true, - value: toJSON, - } -}); module.exports = { PerformanceEntry, diff --git a/src/histogram.cc b/src/histogram.cc index d21cf2883a0ca8..6fbb0eda6c0792 100644 --- a/src/histogram.cc +++ b/src/histogram.cc @@ -1,8 +1,10 @@ #include "histogram.h" // NOLINT(build/include_inline) -#include "histogram-inl.h" #include "base_object-inl.h" +#include "histogram-inl.h" #include "memory_tracker-inl.h" #include "node_errors.h" +#include "node_external_reference.h" + namespace node { using v8::BigInt; @@ -197,6 +199,21 @@ Local HistogramBase::GetConstructorTemplate( return tmpl; } +void HistogramBase::RegisterExternalReferences( + ExternalReferenceRegistry* registry) { + registry->Register(New); + registry->Register(GetExceeds); + registry->Register(GetMin); + registry->Register(GetMax); + registry->Register(GetMean); + registry->Register(GetStddev); + registry->Register(GetPercentile); + registry->Register(GetPercentiles); + registry->Register(DoReset); + registry->Register(Record); + registry->Register(RecordDelta); +} + void HistogramBase::Initialize(Environment* env, Local target) { env->SetConstructorFunction(target, "Histogram", GetConstructorTemplate(env)); } @@ -240,6 +257,20 @@ Local IntervalHistogram::GetConstructorTemplate( return tmpl; } +void IntervalHistogram::RegisterExternalReferences( + ExternalReferenceRegistry* registry) { + registry->Register(GetExceeds); + registry->Register(GetMin); + registry->Register(GetMax); + registry->Register(GetMean); + registry->Register(GetStddev); + registry->Register(GetPercentile); + registry->Register(GetPercentiles); + registry->Register(DoReset); + registry->Register(Start); + registry->Register(Stop); +} + IntervalHistogram::IntervalHistogram( Environment* env, Local wrap, diff --git a/src/histogram.h b/src/histogram.h index 8c164f54cfd9ed..00b4f7796f8be6 100644 --- a/src/histogram.h +++ b/src/histogram.h @@ -18,6 +18,8 @@ namespace node { +class ExternalReferenceRegistry; + constexpr int kDefaultHistogramFigures = 3; class Histogram : public MemoryRetainer { @@ -78,6 +80,7 @@ class HistogramBase : public BaseObject, public HistogramImpl { static v8::Local GetConstructorTemplate( Environment* env); static void Initialize(Environment* env, v8::Local target); + static void RegisterExternalReferences(ExternalReferenceRegistry* registry); static BaseObjectPtr Create( Environment* env, @@ -154,6 +157,8 @@ class IntervalHistogram : public HandleWrap, public HistogramImpl { RESET }; + static void RegisterExternalReferences(ExternalReferenceRegistry* registry); + static v8::Local GetConstructorTemplate( Environment* env); diff --git a/src/node_external_reference.h b/src/node_external_reference.h index 2d6bc34322fd61..094558783f770e 100644 --- a/src/node_external_reference.h +++ b/src/node_external_reference.h @@ -61,6 +61,7 @@ class ExternalReferenceRegistry { V(heap_utils) \ V(messaging) \ V(native_module) \ + V(performance) \ V(process_methods) \ V(process_object) \ V(task_queue) \ diff --git a/src/node_perf.cc b/src/node_perf.cc index 8c5778ecb10bb0..acbb0e0d902c3e 100644 --- a/src/node_perf.cc +++ b/src/node_perf.cc @@ -1,10 +1,11 @@ +#include "node_perf.h" #include "aliased_buffer.h" #include "env-inl.h" #include "histogram-inl.h" #include "memory_tracker-inl.h" -#include "node_internals.h" -#include "node_perf.h" #include "node_buffer.h" +#include "node_external_reference.h" +#include "node_internals.h" #include "node_process-inl.h" #include "util-inl.h" @@ -250,6 +251,12 @@ void ELDHistogram::Initialize(Environment* env, Local target) { env->SetConstructorFunction(target, "ELDHistogram", tmpl); } +void ELDHistogram::RegisterExternalReferences( + ExternalReferenceRegistry* registry) { + registry->Register(New); + IntervalHistogram::RegisterExternalReferences(registry); +} + ELDHistogram::ELDHistogram( Environment* env, Local wrap, @@ -274,6 +281,15 @@ void ELDHistogram::OnInterval() { "stddev", histogram()->Stddev()); } +void GetTimeOrigin(const FunctionCallbackInfo& args) { + args.GetReturnValue().Set(Number::New(args.GetIsolate(), timeOrigin / 1e6)); +} + +void GetTimeOriginTimeStamp(const FunctionCallbackInfo& args) { + args.GetReturnValue().Set( + Number::New(args.GetIsolate(), timeOriginTimestamp / MICROS_PER_MILLIS)); +} + void Initialize(Local target, Local unused, Local context, @@ -308,6 +324,8 @@ void Initialize(Local target, RemoveGarbageCollectionTracking); env->SetMethod(target, "notify", Notify); env->SetMethod(target, "loopIdleTime", LoopIdleTime); + env->SetMethod(target, "getTimeOrigin", GetTimeOrigin); + env->SetMethod(target, "getTimeOriginTimestamp", GetTimeOriginTimeStamp); Local constants = Object::New(isolate); @@ -344,17 +362,6 @@ void Initialize(Local target, PropertyAttribute attr = static_cast(ReadOnly | DontDelete); - target->DefineOwnProperty(context, - FIXED_ONE_BYTE_STRING(isolate, "timeOrigin"), - Number::New(isolate, timeOrigin / 1e6), - attr).ToChecked(); - - target->DefineOwnProperty( - context, - FIXED_ONE_BYTE_STRING(isolate, "timeOriginTimestamp"), - Number::New(isolate, timeOriginTimestamp / MICROS_PER_MILLIS), - attr).ToChecked(); - target->DefineOwnProperty(context, env->constants_string(), constants, @@ -364,7 +371,21 @@ void Initialize(Local target, ELDHistogram::Initialize(env, target); } +void RegisterExternalReferences(ExternalReferenceRegistry* registry) { + registry->Register(MarkMilestone); + registry->Register(SetupPerformanceObservers); + registry->Register(InstallGarbageCollectionTracking); + registry->Register(RemoveGarbageCollectionTracking); + registry->Register(Notify); + registry->Register(LoopIdleTime); + registry->Register(GetTimeOrigin); + registry->Register(GetTimeOriginTimeStamp); + HistogramBase::RegisterExternalReferences(registry); + ELDHistogram::RegisterExternalReferences(registry); +} } // namespace performance } // namespace node NODE_MODULE_CONTEXT_AWARE_INTERNAL(performance, node::performance::Initialize) +NODE_MODULE_EXTERNAL_REFERENCE(performance, + node::performance::RegisterExternalReferences) diff --git a/src/node_perf.h b/src/node_perf.h index 33cf9f2ec651bf..64913ab9de7c61 100644 --- a/src/node_perf.h +++ b/src/node_perf.h @@ -3,10 +3,11 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS -#include "node.h" -#include "node_perf_common.h" #include "base_object-inl.h" #include "histogram.h" +#include "node.h" +#include "node_internals.h" +#include "node_perf_common.h" #include "v8.h" #include "uv.h" @@ -16,6 +17,7 @@ namespace node { class Environment; +class ExternalReferenceRegistry; namespace performance { @@ -160,6 +162,7 @@ using GCPerformanceEntry = PerformanceEntry; class ELDHistogram : public IntervalHistogram { public: + static void RegisterExternalReferences(ExternalReferenceRegistry* registry); static void Initialize(Environment* env, v8::Local target); static void New(const v8::FunctionCallbackInfo& args); diff --git a/test/parallel/test-bootstrap-modules.js b/test/parallel/test-bootstrap-modules.js index f18f85728d36e3..0ca00f31adce8c 100644 --- a/test/parallel/test-bootstrap-modules.js +++ b/test/parallel/test-bootstrap-modules.js @@ -23,6 +23,7 @@ const expectedModules = new Set([ 'Internal Binding module_wrap', 'Internal Binding native_module', 'Internal Binding options', + 'Internal Binding performance', 'Internal Binding process_methods', 'Internal Binding report', 'Internal Binding serdes', @@ -60,6 +61,7 @@ const expectedModules = new Set([ 'NativeModule internal/fs/rimraf', 'NativeModule internal/fs/watchers', 'NativeModule internal/heap_utils', + 'NativeModule internal/histogram', 'NativeModule internal/idna', 'NativeModule internal/linkedlist', 'NativeModule internal/modules/run_main', @@ -77,6 +79,15 @@ const expectedModules = new Set([ 'NativeModule internal/modules/esm/translators', 'NativeModule internal/process/esm_loader', 'NativeModule internal/options', + 'NativeModule internal/perf/event_loop_delay', + 'NativeModule internal/perf/event_loop_utilization', + 'NativeModule internal/perf/nodetiming', + 'NativeModule internal/perf/observe', + 'NativeModule internal/perf/performance', + 'NativeModule internal/perf/performance_entry', + 'NativeModule internal/perf/timerify', + 'NativeModule internal/perf/usertiming', + 'NativeModule internal/perf/utils', 'NativeModule internal/priority_queue', 'NativeModule internal/process/execution', 'NativeModule internal/process/per_thread', @@ -116,6 +127,7 @@ const expectedModules = new Set([ 'NativeModule internal/blob', 'NativeModule async_hooks', 'NativeModule path', + 'NativeModule perf_hooks', 'NativeModule querystring', 'NativeModule stream', 'NativeModule stream/promises',