import fs from 'fs' /** 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() export function readFileCached(path) { let entry = fdCache.get(path) if (entry === undefined) { try { const fd = fs.openSync(path, 'r') entry = { fd } fdCache.set(path, entry) } catch { fdCache.set(path, null) return null } } if (!entry) return null try { 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 } } /** * Read a file using the shared small buffer, no FD caching. * Good for dynamic paths (per-PID, per-cgroup) where open+close each tick is acceptable * but Buffer allocation is not. */ export function readFileBuf(path) { try { const fd = fs.openSync(path, 'r') try { const bytes = fs.readSync(fd, SMALL_BUF, 0, SMALL_BUF.length, 0) return SMALL_BUF.toString('utf8', 0, bytes) } finally { fs.closeSync(fd) } } catch { return null } } export function closeFdCache() { for (const [path, entry] of fdCache) { if (entry) { try { fs.closeSync(entry.fd) } catch {} } } fdCache.clear() }