perf(diag): enrich event-loop-delay log with active-resource histogram

Make the single high-concurrency measurement decisive. The ELD line now appends process.getActiveResourcesInfo() as a compact type-histogram, so one run splits all three readings in a single line: high mean/p99 means the main thread is CPU-blocked (workers/cap justified); low delay with many TCPSocketWrap/FSReqCallback/GetAddrInfoReqWrap resources means IO-bound queueing (threadpool/socket tuning, not workers); low delay with few resources means it is not saturated at all. Pure metrics — no credential-redaction path touched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Administrator 2026-06-21 04:20:32 +02:00
parent 854740d57c
commit 901cd823dd

10
main.js
View File

@ -197,7 +197,15 @@ function _maybeLogEventLoopDelay(activeJobs) {
const max = (_eventLoopDelay.max / ns).toFixed(1);
const p99 = (_eventLoopDelay.percentile(99) / ns).toFixed(1);
const stddev = (_eventLoopDelay.stddev / ns).toFixed(1);
logInfo('perf', `eventloop-delay active=${activeJobs} mean=${mean}ms p99=${p99}ms max=${max}ms stddev=${stddev}ms threadpool=${process.env.UV_THREADPOOL_SIZE}`);
let resStr = '';
try {
const info = process.getActiveResourcesInfo();
const hist = {};
for (const t of info) hist[t] = (hist[t] || 0) + 1;
const top = Object.entries(hist).sort((a, b) => b[1] - a[1]).slice(0, 6).map(([k, v]) => `${k}:${v}`).join(',');
resStr = ` resources=${info.length} {${top}}`;
} catch {}
logInfo('perf', `eventloop-delay active=${activeJobs} mean=${mean}ms p99=${p99}ms max=${max}ms stddev=${stddev}ms threadpool=${process.env.UV_THREADPOOL_SIZE}${resStr}`);
_eventLoopDelay.reset();
} catch {}
}