目次を表示する

Async Local Storage Deep Dive 2026 ─ 内部実装・落とし穴・性能を 9 章で読み解く

性能を読み解く(公開ベンチから)

性能を読み解く(公開ベンチから)

ここまで内部実装の進化を 4 段階に分けて見てきた。読者として最後に気になるのは「で、結局自分のアプリではどれくらいの差なの?」だろう。

ベンチを自前で取りたいところだが、Node.js の性能は環境(CPU/メモリ/カーネル)と workload(CPU bound / I/O bound)で大きく変わる。むしろ信頼できる公開ベンチを文脈付きで読む方が実用的だ。この章ではそれをやる。

ベンチを読む前に注意すべきこと

  1. microbench と実アプリの数値は別物。microbench は ALS 単体の overhead を測るが、実アプリでは I/O や DB 待ちが支配的で ALS の overhead は薄まる
  2. 環境を必ず確認。CPU 世代、Node のマイナーバージョン、libuv のスレッドプール設定で結果が変わる
  3. ALS あり / なしだけでなくNode のバージョン間の比較も意識する。同じ ALS でも 22 と 24 では中身が違う

各ベンチを実装と紐づけて読む

Issue #34493(2020):「97% 性能低下」

createHook 実装の悪名。報告者のベンチでは、async ヘビーな環境で 97% のスループット低下。第 3 章で見たように、当時の ALS は全 Promise 生成で C++ → JS の境界跨ぎが起きる構造だったため、Promise 数 × 境界跨ぎコストが積み重なる。

PR #36394 ベンチ(2020-21):271k → 1.25M ops/sec

第 4 章の主役。V8 PromiseHook API 刷新の効果:

状態スループット備考
disabled(フックなし)1,672,015 ops/sec上限
旧 enabled271,514 ops/sec-83.7%
新 enabled1,250,448 ops/sec-25.2%

約 4.6 倍の改善。境界跨ぎの除去が効いた。

Platformatic ベンチ(2025):実アプリ近傍

Platformatic Blog “The Hidden Cost of Async Context” の実測。環境は Intel i7-7700 / 62GB RAM / 100 並行接続 × 10 req × 10 秒。HTTP サーバー越しの req/s。

NodeALS なしALS あり低下率
v22.17.156,446 req/s50,913 req/s-9.8%
v24.4.157,301 req/s53,450 req/s-6.7%

第 5 章で見た AsyncContextFrame が、v22 → v24 で約 5% の改善(ALS 自体)に直接対応する。実アプリ環境で 6-10% の overhead は、運用上は許容範囲と判断するチームが多い数値だ。

Platformatic ベンチ:OpenTelemetry の重さ

同じベンチで OpenTelemetry の full instrumentation を有効にすると:

Nodeスループットベースから
v24 + ALS のみ53,450 req/s-6.7%
v24 + OpenTelemetry full10,640 req/s-81.4%

ALS だけなら 6.7% だが、OpenTelemetry の全部入りは 80% 超の低下。これは ALS の問題ではない ── OpenTelemetry が async_hooks.createHook() を直接使っており、フック発火が大量に走るためだ。第 2 章で公式が「migrate away」と書いていたまさにその構造を、APM ツールが踏み抜いている。

第 8 章で扱う 2026/1 の DoS 脆弱性で「APM ツールが軒並み被弾した」のも、この依存関係に根がある。

Aschen microbench(2020 頃):25% 低下

Aschen の Gist は ALS 単体の microbench で 25% 低下を計測した。これは Issue #34493 と同時代の数値で、第 3 章で見た旧実装 の素のコスト。同じ条件で v24 を測ると数値は劇的に変わる(公開された具体値はないが、PR #36394 の延長で 70-80% の改善が想定される)。

Kuzzle 実アプリ(2020):8% 低下

旧実装でも実アプリでは 8% 程度の低下に収まったというデータ。microbench の 25% と差があるのは「実アプリでは I/O 待ちが支配的」だから。これは「数字を見る時の解像度」を上げる材料:microbench で 25% 低下 = 実アプリで 25% 遅くなる、ではない

数値のサマリ

graph TB
  A[Node 13.10 当初実装<br/>microbench -25%<br/>Issue #34493 では -97% 報告]
  B[Node 16+ V8 PromiseHook<br/>microbench で 4.6x 改善]
  C[Node 24 AsyncContextFrame<br/>実アプリで -6.7%<br/>v22 比 約 5% 改善]
  D[OpenTelemetry full<br/>-81.4%]

  A --> B --> C
  C -.APM 系は別問題.- D

  style A fill:#ffe1e1
  style B fill:#fff4e1
  style C fill:#e1ffe1
  style D fill:#ffe1e1

運用判断の指針

これらの数値から、運用上の判断は次のようにできる:

  • 新規プロジェクト: ALS をリクエストスコープに使うのは合理的。Node 22+ で性能影響は ~10% 内、Node 24 では ~7% 内
  • 既存アプリで ALS を導入する場合: 自分の workload(I/O 中心 vs CPU 中心)を意識。I/O 中心ならほぼ気にならない、CPU 中心なら測ってから
  • APM / OpenTelemetry 全面導入は慎重に: 80% 落ちる workload もある。サンプリング・選択的計装で抑える前提

この章の要点

  • 公開ベンチは microbench と実アプリで数値感が違う。前者は内部 overhead、後者は workload で薄まった結果
  • 旧実装(〜Node 15)は microbench で深刻、実アプリでは中程度(Kuzzle 8% / Issue 97%)
  • PR #36394 で 4.6x 改善、Node 24 でさらに ~5% 改善(実アプリベンチ)
  • OpenTelemetry の 80% 低下は ALS ではなく createHook 直叩きが原因
  • 運用判断: ALS は ~10% で許容、APM 全面導入は別途検討

次章への問いかけ

数値で見えた。だが、この OpenTelemetry の話の延長線上で、2026 年 1 月、本当の事件が起きた

なぜ React Server Components / Next.js は無事で、APM 各社は被弾したのか。次章で見る。