跳到主要内容

GC

2024年12月25日
柏拉文
越努力,越幸运

一、nodejs_gc_duration_seconds


1.1 认识

nodejs_gc_duration_seconds 记录垃圾回收(GC)的持续时间。

1.2 计算

实现计算垃圾回收(GC)的持续时间:

  1. 基于 perf_hooks.PerformanceObserver 的方案:这是更精确的方式,使用 Node.jsperf_hooks 模块中的 PerformanceObserver 监听垃圾回收(GC)事件。

  2. 基于 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();
}