テック技報最新号へ →
コード

Node.js: 遅いエンドポイントは I/O とは限らない。monitorEventLoopDelay でイベントループの詰まりを測る

巨大な JSON.parse や crypto.pbkdf2Sync のような同期処理が 1 回走るだけで、その間ほかの全リクエストが止まる。perf_hooks.monitorEventLoopDelay() でイベントループの遅延を測って p99 を監視し、重い CPU 処理は worker_threads に逃がす。

@amitsinha__07 · 投稿 2026-10-24
#nodejs#performance#event-loop#monitoring

症状

  • 特定のエンドポイントではなく、無関係なリクエストまでときどき遅くなる。
  • DB や外部 API のレイテンシは正常なのに、アプリのレスポンスタイムだけ跳ねる。

Node はシングルスレッドのイベントループで動くので、同期処理が占有している間は他のコールバックが実行されない。

測り方

js
import { monitorEventLoopDelay } from "node:perf_hooks";

const h = monitorEventLoopDelay({ resolution: 20 }); // ms
h.enable();

setInterval(() => {
  // 値はナノ秒
  const p99ms = h.percentile(99) / 1e6;
  metrics.gauge("nodejs.eventloop.delay.p99_ms", p99ms);
  h.reset();
}, 10_000).unref();

p99 が数十 ms〜数百 ms に跳ねるなら、どこかで同期処理がループを塞いでいる。原因の特定は node --cpu-prof や --inspect のプロファイラで。

対処

  • パスワードハッシュは crypto.pbkdf2 / crypto.scrypt の非同期版を使う(libuv のスレッドプールで動く)。
  • 巨大な JSON の parse/stringify、画像処理、圧縮などは worker_threads(Piscina などのプール)に移す。
  • そもそも巨大なボディを受けないよう上限を付ける。

注意点

  • monitorEventLoopDelay は Node 11.10 以降。OpenTelemetry の Node ランタイム計測や prom-client の既定メトリクスにも同等の値がある。

出典

X の元の投稿を開く