In /proc/stat, guest is already inside user (and guest_nice inside nice). Peardata was adding guest into the total again, which shrinks every other slice — including idle.
readFileCached capped at 64KB. On 56-core hosts /proc/interrupts (and similar) often exceeds that — reads were silently truncated. Buffer now grows (up to 1MB). That didn’t break system.cpu idle (aggregate line is first), but it was a real high-core regression.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import fs from 'fs'
|
||||
|
||||
const READ_BUF = Buffer.alloc(65536)
|
||||
/** Shared buffer — grows if a read fills it (e.g. /proc/interrupts on 56-core hosts). */
|
||||
let readBuf = Buffer.alloc(65536)
|
||||
const MAX_READ_BUF = 1024 * 1024
|
||||
const SMALL_BUF = Buffer.alloc(8192)
|
||||
const fdCache = new Map()
|
||||
|
||||
@@ -18,8 +20,21 @@ export function readFileCached(path) {
|
||||
}
|
||||
if (!entry) return null
|
||||
try {
|
||||
const bytesRead = fs.readSync(entry.fd, READ_BUF, 0, READ_BUF.length, 0)
|
||||
return READ_BUF.toString('utf8', 0, bytesRead)
|
||||
let bytesRead = fs.readSync(entry.fd, readBuf, 0, readBuf.length, 0)
|
||||
// Filled the buffer → likely truncated; grow and retry (common on high-core /proc files)
|
||||
while (bytesRead === readBuf.length && readBuf.length < MAX_READ_BUF) {
|
||||
readBuf = Buffer.alloc(Math.min(readBuf.length * 4, MAX_READ_BUF))
|
||||
bytesRead = fs.readSync(entry.fd, readBuf, 0, readBuf.length, 0)
|
||||
}
|
||||
if (bytesRead === readBuf.length) {
|
||||
// Still truncated at cap — full read for correctness
|
||||
try {
|
||||
return fs.readFileSync(path, 'utf8')
|
||||
} catch {
|
||||
/* fall through with truncated buffer */
|
||||
}
|
||||
}
|
||||
return readBuf.toString('utf8', 0, bytesRead)
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user