Skip to content

Commit 9b4a49c

Browse files
fanatidtargos
authored andcommitted
perf_hooks: remove GC callbacks on zero observers count
When all existed PerformanceObserver instances removed for type `gc` GC callbacks should be removed. PR-URL: #29444 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Minwoo Jung <[email protected]>
1 parent a9d16b5 commit 9b4a49c

File tree

2 files changed

+34
-16
lines changed

2 files changed

+34
-16
lines changed

lib/perf_hooks.js

+12-8
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ const {
1515
timeOriginTimestamp,
1616
timerify,
1717
constants,
18-
setupGarbageCollectionTracking
18+
installGarbageCollectionTracking,
19+
removeGarbageCollectionTracking
1920
} = internalBinding('performance');
2021

2122
const {
@@ -281,8 +282,6 @@ class PerformanceObserverEntryList {
281282
}
282283
}
283284

284-
let gcTrackingIsEnabled = false;
285-
286285
class PerformanceObserver extends AsyncResource {
287286
constructor(callback) {
288287
if (typeof callback !== 'function') {
@@ -319,6 +318,7 @@ class PerformanceObserver extends AsyncResource {
319318
}
320319

321320
disconnect() {
321+
const observerCountsGC = observerCounts[NODE_PERFORMANCE_ENTRY_TYPE_GC];
322322
const types = this[kTypes];
323323
const keys = Object.keys(types);
324324
for (var n = 0; n < keys.length; n++) {
@@ -329,6 +329,10 @@ class PerformanceObserver extends AsyncResource {
329329
}
330330
}
331331
this[kTypes] = {};
332+
if (observerCountsGC === 1 &&
333+
observerCounts[NODE_PERFORMANCE_ENTRY_TYPE_GC] === 0) {
334+
removeGarbageCollectionTracking();
335+
}
332336
}
333337

334338
observe(options) {
@@ -342,12 +346,8 @@ class PerformanceObserver extends AsyncResource {
342346
if (entryTypes.length === 0) {
343347
throw new ERR_VALID_PERFORMANCE_ENTRY_TYPE();
344348
}
345-
if (entryTypes.includes(NODE_PERFORMANCE_ENTRY_TYPE_GC) &&
346-
!gcTrackingIsEnabled) {
347-
setupGarbageCollectionTracking();
348-
gcTrackingIsEnabled = true;
349-
}
350349
this.disconnect();
350+
const observerCountsGC = observerCounts[NODE_PERFORMANCE_ENTRY_TYPE_GC];
351351
this[kBuffer][kEntries] = [];
352352
L.init(this[kBuffer][kEntries]);
353353
this[kBuffering] = Boolean(options.buffered);
@@ -359,6 +359,10 @@ class PerformanceObserver extends AsyncResource {
359359
L.append(list, item);
360360
observerCounts[entryType]++;
361361
}
362+
if (observerCountsGC === 0 &&
363+
observerCounts[NODE_PERFORMANCE_ENTRY_TYPE_GC] === 1) {
364+
installGarbageCollectionTracking();
365+
}
362366
}
363367
}
364368

src/node_perf.cc

+22-8
Original file line numberDiff line numberDiff line change
@@ -277,19 +277,29 @@ void MarkGarbageCollectionEnd(Isolate* isolate,
277277
});
278278
}
279279

280-
static void SetupGarbageCollectionTracking(
280+
void GarbageCollectionCleanupHook(void* data) {
281+
Environment* env = static_cast<Environment*>(data);
282+
env->isolate()->RemoveGCPrologueCallback(MarkGarbageCollectionStart, data);
283+
env->isolate()->RemoveGCEpilogueCallback(MarkGarbageCollectionEnd, data);
284+
}
285+
286+
static void InstallGarbageCollectionTracking(
281287
const FunctionCallbackInfo<Value>& args) {
282288
Environment* env = Environment::GetCurrent(args);
283289

284290
env->isolate()->AddGCPrologueCallback(MarkGarbageCollectionStart,
285291
static_cast<void*>(env));
286292
env->isolate()->AddGCEpilogueCallback(MarkGarbageCollectionEnd,
287293
static_cast<void*>(env));
288-
env->AddCleanupHook([](void* data) {
289-
Environment* env = static_cast<Environment*>(data);
290-
env->isolate()->RemoveGCPrologueCallback(MarkGarbageCollectionStart, data);
291-
env->isolate()->RemoveGCEpilogueCallback(MarkGarbageCollectionEnd, data);
292-
}, env);
294+
env->AddCleanupHook(GarbageCollectionCleanupHook, env);
295+
}
296+
297+
static void RemoveGarbageCollectionTracking(
298+
const FunctionCallbackInfo<Value> &args) {
299+
Environment* env = Environment::GetCurrent(args);
300+
301+
env->RemoveCleanupHook(GarbageCollectionCleanupHook, env);
302+
GarbageCollectionCleanupHook(env);
293303
}
294304

295305
// Gets the name of a function
@@ -575,8 +585,12 @@ void Initialize(Local<Object> target,
575585
env->SetMethod(target, "markMilestone", MarkMilestone);
576586
env->SetMethod(target, "setupObservers", SetupPerformanceObservers);
577587
env->SetMethod(target, "timerify", Timerify);
578-
env->SetMethod(
579-
target, "setupGarbageCollectionTracking", SetupGarbageCollectionTracking);
588+
env->SetMethod(target,
589+
"installGarbageCollectionTracking",
590+
InstallGarbageCollectionTracking);
591+
env->SetMethod(target,
592+
"removeGarbageCollectionTracking",
593+
RemoveGarbageCollectionTracking);
580594
env->SetMethod(target, "notify", Notify);
581595

582596
Local<Object> constants = Object::New(isolate);

0 commit comments

Comments
 (0)