CPU and state topology is cached for 30s.
CI / test (push) Has been cancelled
Release rolling / release (push) Has been cancelled

This commit is contained in:
Raven Scott
2026-07-21 13:42:34 -04:00
parent 26298fb8d4
commit 47bd72f5b6
2 changed files with 61 additions and 31 deletions
+21 -12
View File
@@ -216,6 +216,7 @@ export class CgroupsCollector extends EventEmitter {
/** @type {Array<{ id: string, title: string, path: string }>|null} */
this._cgCache = null
this._cgTs = 0
this._cgTick = 0
}
start() {
@@ -285,6 +286,9 @@ export class CgroupsCollector extends EventEmitter {
}
}
const cgList = this._cgCache
const doMemDetail = this._cgTick % 5 === 0
const doPressure = this._cgTick % 3 === 0
this._cgTick++
for (const cg of cgList) {
const title = resolveContainerLabel(cg.title, this._names)
@@ -347,7 +351,10 @@ export class CgroupsCollector extends EventEmitter {
},
})
const memStat = profile('memStat:' + cg.id.slice(0,20), () => parseMemoryStat(cg.path))
let memStat = null
if (doMemDetail) {
memStat = profile('memStat:' + cg.id.slice(0,20), () => parseMemoryStat(cg.path))
}
if (memStat) {
batch.push({
chart: memDetailDef.id,
@@ -374,17 +381,19 @@ export class CgroupsCollector extends EventEmitter {
values: { throttled: throttlePct },
})
for (const kind of ['cpu', 'memory', 'io']) {
const some10 = parsePressureSome10(cg.path, kind)
if (some10 == null) continue
const pressureDef = makeCgroupPressureChart(cg.id, title, kind)
registerChart(pressureDef)
batch.push({
chart: pressureDef.id,
context: 'cgroup.pressure',
ts,
values: { some10 },
})
if (doPressure) {
for (const kind of ['cpu', 'memory', 'io']) {
const some10 = parsePressureSome10(cg.path, kind)
if (some10 == null) continue
const pressureDef = makeCgroupPressureChart(cg.id, title, kind)
registerChart(pressureDef)
batch.push({
chart: pressureDef.id,
context: 'cgroup.pressure',
ts,
values: { some10 },
})
}
}
this.prev.set(cg.id, {
+40 -19
View File
@@ -208,32 +208,53 @@ export function collectNumaNodes(batch, ts) {
*/
export function collectCpuidle(batch, ts, dtSec, state) {
if (os.platform() !== 'linux') return
const cpuRoot = '/sys/devices/system/cpu'
let dirs
try {
dirs = fs.readdirSync(cpuRoot).filter((d) => /^cpu\d+$/.test(d))
} catch {
return
// cache cpuidle state paths for 30s — topology doesn't change at runtime
let cpuidlePaths = state._cpuidlePaths
const now = Date.now()
if (!cpuidlePaths || now - cpuidlePaths.ts > 30000) {
const cpuRoot = '/sys/devices/system/cpu'
let dirs
try {
dirs = fs.readdirSync(cpuRoot).filter((d) => /^cpu\d+$/.test(d))
} catch {
return
}
/** @type {Record<string, Array<{ nameFile: string, timeFile: string }>>} */
const entries = {}
for (const d of dirs) {
const coreId = d.slice(3)
const idleDir = path.join(cpuRoot, d, 'cpuidle')
let states
try {
states = fs.readdirSync(idleDir).filter((s) => /^state\d+$/.test(s))
} catch {
continue
}
const files = []
for (const s of states) {
files.push({
nameFile: path.join(idleDir, s, 'name'),
timeFile: path.join(idleDir, s, 'time'),
})
}
if (files.length) entries[coreId] = files
}
cpuidlePaths = { ts: now, entries, cpuDirs: dirs }
state._cpuidlePaths = cpuidlePaths
}
const { entries } = cpuidlePaths
const prevAll = state.lastIdle || {}
/** @type {Record<string, Record<string, number>>} */
const nextAll = {}
for (const d of dirs) {
const coreId = d.slice(3)
const idleDir = path.join(cpuRoot, d, 'cpuidle')
let states
try {
states = fs.readdirSync(idleDir).filter((s) => /^state\d+$/.test(s))
} catch {
continue
}
for (const coreId of Object.keys(entries)) {
const files = entries[coreId]
/** @type {Record<string, number>} */
const times = {}
for (const s of states) {
const name = (readFile(path.join(idleDir, s, 'name')) || s).trim().toLowerCase().replace(/\s+/g, '_')
const t = Number(readFile(path.join(idleDir, s, 'time')) || 0) // µs
times[name || s] = t
for (const { nameFile, timeFile } of files) {
const name = (readFile(nameFile) || '').trim().toLowerCase().replace(/\s+/g, '_')
const t = Number(readFile(timeFile) || 0) // µs
times[name || 'state'] = t
}
nextAll[coreId] = times
const prev = prevAll[coreId]