From e81c6c81de712983959a2dd4e01048b4fee6fd7c Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 1 Feb 2019 01:04:44 +0800 Subject: [PATCH] perf_hooks: only enable GC tracking when it's requested Previously a GC prologue callback and a GC epilogue callback are always unconditionally enabled during bootstrap when the `performance` binding is loaded, even when the user does not use the performance timeline API to enable GC tracking. This patch makes the callback addition conditional and only enables them when the user explicitly requests `observer.observe(['gc'])` to avoid the overhead. PR-URL: https://github.com/nodejs/node/pull/25853 Reviewed-By: Anna Henningsen Reviewed-By: Gus Caplan Reviewed-By: James M Snell --- lib/perf_hooks.js | 10 +++++++++- src/node_perf.cc | 8 +++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/perf_hooks.js b/lib/perf_hooks.js index 5862e35d738058..041bbf68f2f6c4 100644 --- a/lib/perf_hooks.js +++ b/lib/perf_hooks.js @@ -11,7 +11,8 @@ const { timeOrigin, timeOriginTimestamp, timerify, - constants + constants, + setupGarbageCollectionTracking } = internalBinding('performance'); const { @@ -275,6 +276,8 @@ class PerformanceObserverEntryList { } } +let gcTrackingIsEnabled = false; + class PerformanceObserver extends AsyncResource { constructor(callback) { if (typeof callback !== 'function') { @@ -336,6 +339,11 @@ class PerformanceObserver extends AsyncResource { if (entryTypes.length === 0) { throw new errors.ERR_VALID_PERFORMANCE_ENTRY_TYPE(); } + if (entryTypes.includes(NODE_PERFORMANCE_ENTRY_TYPE_GC) && + !gcTrackingIsEnabled) { + setupGarbageCollectionTracking(); + gcTrackingIsEnabled = true; + } this.disconnect(); this[kBuffer][kEntries] = []; L.init(this[kBuffer][kEntries]); diff --git a/src/node_perf.cc b/src/node_perf.cc index cefd0ff26dbf95..33dd1d2051872c 100644 --- a/src/node_perf.cc +++ b/src/node_perf.cc @@ -296,8 +296,10 @@ void MarkGarbageCollectionEnd(Isolate* isolate, entry); } +static void SetupGarbageCollectionTracking( + const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); -inline void SetupGarbageCollectionTracking(Environment* env) { env->isolate()->AddGCPrologueCallback(MarkGarbageCollectionStart, static_cast(env)); env->isolate()->AddGCEpilogueCallback(MarkGarbageCollectionEnd, @@ -416,6 +418,8 @@ void Initialize(Local target, env->SetMethod(target, "markMilestone", MarkMilestone); env->SetMethod(target, "setupObservers", SetupPerformanceObservers); env->SetMethod(target, "timerify", Timerify); + env->SetMethod( + target, "setupGarbageCollectionTracking", SetupGarbageCollectionTracking); Local constants = Object::New(isolate); @@ -452,8 +456,6 @@ void Initialize(Local target, env->constants_string(), constants, attr).ToChecked(); - - SetupGarbageCollectionTracking(env); } } // namespace performance