V8's Minor Mark-Sweep collector, enabled with the --minor-ms flag (available since Node.js 22), reports garbage collection performance entries with kind kGCTypeMinorMarkSweep (value 2). perf_hooks exposed constants for every other GC kind (major, minor, incremental, weakcb) but not this one, so consumers inspecting performanceEntry.detail.kind had no constant to compare against and saw an unmapped value. Expose it as perf_hooks.constants.NODE_PERFORMANCE_GC_MINOR_MARK_SWEEP, mirroring the existing v8::GCType mappings, and document it alongside the other GC kinds. Signed-off-by: Attila Szegedi <attila.szegedi@datadoghq.com> PR-URL: https://github.com/nodejs/node/pull/63877 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Ilyas Shabi <ilyasshabi94@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
56 lines
1.6 KiB
JavaScript
56 lines
1.6 KiB
JavaScript
// Flags: --expose-gc --no-warnings
|
|
'use strict';
|
|
|
|
const common = require('../common');
|
|
const assert = require('assert');
|
|
const {
|
|
PerformanceObserver,
|
|
constants
|
|
} = require('perf_hooks');
|
|
|
|
const {
|
|
NODE_PERFORMANCE_GC_MAJOR,
|
|
NODE_PERFORMANCE_GC_MINOR,
|
|
NODE_PERFORMANCE_GC_MINOR_MARK_SWEEP,
|
|
NODE_PERFORMANCE_GC_INCREMENTAL,
|
|
NODE_PERFORMANCE_GC_WEAKCB,
|
|
NODE_PERFORMANCE_GC_FLAGS_FORCED
|
|
} = constants;
|
|
|
|
const kinds = [
|
|
NODE_PERFORMANCE_GC_MAJOR,
|
|
NODE_PERFORMANCE_GC_MINOR,
|
|
NODE_PERFORMANCE_GC_MINOR_MARK_SWEEP,
|
|
NODE_PERFORMANCE_GC_INCREMENTAL,
|
|
NODE_PERFORMANCE_GC_WEAKCB,
|
|
];
|
|
|
|
// Adding an observer should force at least one gc to appear
|
|
{
|
|
const obs = new PerformanceObserver(common.mustCallAtLeast((list) => {
|
|
const entry = list.getEntries()[0];
|
|
assert(entry);
|
|
assert.strictEqual(entry.name, 'gc');
|
|
assert.strictEqual(entry.entryType, 'gc');
|
|
assert(kinds.includes(entry.detail.kind));
|
|
assert.strictEqual(entry.detail.flags, NODE_PERFORMANCE_GC_FLAGS_FORCED);
|
|
assert.strictEqual(typeof entry.startTime, 'number');
|
|
assert(entry.startTime < 1e4, 'startTime should be relative to performance.timeOrigin.');
|
|
assert.strictEqual(typeof entry.duration, 'number');
|
|
obs.disconnect();
|
|
}));
|
|
obs.observe({ entryTypes: ['gc'] });
|
|
globalThis.gc();
|
|
// Keep the event loop alive to witness the GC async callback happen.
|
|
setImmediate(() => setImmediate(() => 0));
|
|
}
|
|
|
|
// GC should not keep the event loop alive
|
|
{
|
|
let didCall = false;
|
|
process.on('beforeExit', common.mustCall(() => {
|
|
assert(!didCall);
|
|
didCall = true;
|
|
globalThis.gc();
|
|
}));
|
|
}
|