GC
2024年12月25日
一、nodejs_gc_duration_seconds
1.1 认识
nodejs_gc_duration_seconds
记录垃圾回收(GC
)的持续时间。
1.2 计算
实现计算垃圾回收(GC
)的持续时间:
-
基于
perf_hooks.PerformanceObserver
的方案:这是更精确的方式,使用Node.js
的perf_hooks
模块中的PerformanceObserver
监听垃圾回收(GC
)事件。 -
基于
process.hrtime()
的方案:在perf_hooks
不可用的环境中,我们回退到使用process.hrtime()
来手动计算GC
持续时间。
const v8 = require('v8'); // 提供 GC 的访问
const { performance, PerformanceObserver } = require('perf_hooks'); // 使用 perf_hooks
const process = require('process');
// ---方案1:基于 `perf_hooks.PerformanceObserver` 实现---
function monitorGCWithPerfHooks() {
// 通过 PerformanceObserver 来监听性能数据(包括垃圾回收)
const obs = new PerformanceObserver((list, observer) => {
const entries = list.getEntriesByType('measure');
entries.forEach(entry => {
if (entry.name === 'gc') {
const gcDuration = entry.duration / 1000; // 转换为秒
console.log(`GC Duration (perf_hooks): ${gcDuration.toFixed(6)} seconds`);
}
});
});
// 启动监听
obs.observe({ type: 'measure', buffered: true });
// 开始测量垃圾回收时长
v8.setFlagsFromString('--trace-gc'); // 启用 GC 跟踪(通过日志输出)
// 捕获 GC 信息,并通过 PerformanceObserver 记录
setInterval(() => {
performance.mark('gc-start'); // 标记 GC 开始
// 模拟触发 GC(实际上是依赖环境中的垃圾回收事件触发)
global.gc();
performance.mark('gc-end'); // 标记 GC 结束
performance.measure('gc', 'gc-start', 'gc-end'); // 计算并记录 GC 持续时间
}, 1000); // 每秒触发一次 GC 测量
}
// ---方案2:基于 `process.hrtime()` 实现---
function monitorGCWithProcessHrtime() {
let lastGCTime = null;
// 监听垃圾回收
v8.setFlagsFromString('--trace-gc'); // 启用 GC 跟踪(通过日志输出)
setInterval(() => {
const startTime = process.hrtime(); // 获取高精度的时间戳
// 模拟触发垃圾回收
global.gc();
const endTime = process.hrtime(startTime); // 计算时间差
const gcDurationInSeconds = (endTime[0] + endTime[1] / 1e9); // 转换为秒
console.log(`GC Duration (process.hrtime): ${gcDurationInSeconds.toFixed(6)} seconds`);
}, 1000); // 每秒触发一次 GC 测量
}
// 选择方案:首先尝试使用 `perf_hooks`,如果不可用,则使用 `process.hrtime()`
// 方案1:基于 `perf_hooks.PerformanceObserver` 来监控 GC 持续时间
if (performance && PerformanceObserver) {
monitorGCWithPerfHooks();
} else {
// 方案2:降级到 `process.hrtime()`
monitorGCWithProcessHrtime();
}