
Vue Fes Japan 2026で「あなたの await、OS まで届いてる? strace で覗く JavaScript の非同期」というタイトルで登壇しました
こんにちは、製造ビジネステクノロジー部のはすとです。
2026年10月24日に大手町プレイス ホール&カンファレンスで開催されたVue Fes Japan 2026のライトニングトーク枠で、「あなたの await、OS まで届いてる? strace で覗く JavaScript の非同期」というタイトルで5分間お話ししました。本記事では、登壇資料と伝えたかったことをまとめます。
Vue Fes Japan 2026とは
Vue Fes Japanは、Vue.js日本ユーザーグループが主催するフロントエンドのカンファレンスです。公式サイトでは「日本最大級のフロントエンドカンファレンス」と紹介されており、Vue.jsに閉じず、JavaScriptコミュニティで活躍するOSS開発者が集まるお祭りのようなイベントです!
登壇資料
awaitはPromiseを待つだけでOSには届かず、OSに届いていたのはfetch()が返すPromiseを解決するための処理だった、という話です。スライドに載せたログとコードは次のリポジトリに置いています。Dockerがあればdocker compose up --buildで全部の実験を再現できます。
伝えたかったこと
await fetch()と書いたとき、待っている間にOSは何をしているのか。これをstraceで確かめるという内容で、3つの問いで進めました。
計測はNode.js v22.23.3とstrace 6.1で、手元のMacのDocker(Colima)上のDebian 12で行いました。
epoll_pwaitはLinuxの仕組みで、macOSではkqueue、WindowsではIOCPをlibuvが使います。スライドのログはどれもLinuxでの話です。
await した時に、OS には何が届くのか
await fetch()をMARKで挟んでstraceを取ると、socket()でソケットを作り、connect()で接続を始め、write()でGETリクエストを書き込んだあと、Node.jsのスレッドはepoll_pwait()の中で応答が届くまで止まります。届いたらread()で読みます。fetch()が返すPromiseを解決するための処理が、OSまで届いていました。
await Promise.resolve()に置き換えると、MARKの間には何も出ません。awaitはPromiseを待つだけで、OSには何も届いていませんでした。
システムコールを出しているのはlibuvです。libuvはイベントループのpollフェーズで、作ったソケットをepollに登録してからepoll_pwaitを呼びます。epoll_pwaitは、登録したソケットのどれかに応答が届くまでOSに待ってもらう仕組みです。応答が届くとOSがepoll_pwaitを戻し、libuvがreadして、Promiseが解決し、awaitの続きが動きます。
直列と Promise.all は、OS から見ると何が違うのか
ここからは、モックサーバーが300ms待ってから応答します。直列(await fetch(); await fetch())は、1本目のソケットだけを登録してepoll_pwaitで待ち、2本目のsocketとconnectは1本目の応答を読んでから出ています。
Promise.allは、2本ともソケットを作って接続を始めてからepoll_pwaitに入ります。epoll_pwaitは1回で、そのあと2本の応答を読んでいます。
所要時間は直列が約640ms、Promise.allが約330msで、約半分でした。Promise.allが速いのは、awaitで止まる前に2本ともfetch()を呼んでいるためです。2本とも登録してからepoll_pwaitに入れるため、2本分の待ちが1回の待ちに重なります。
Nuxt の useFetch に置き換えると
NuxtのuseFetchでも同じことを試しました。await useFetchを2回並べると直列と同じ形になり、1本目の応答待ちが終わってから2本目のconnectが出ています。
Promise.allで束ねると、2本ともconnectしてからepoll_pwaitが1回で、同じ形になりました。初回リクエストの所要時間は748msと436msです。
まとめとして話したこと
awaitはPromiseを待つだけで、OSには届きません。OSに届いていたのは、fetch()が返すPromiseを解決するための処理でした。JavaScriptが止まったあとにlibuvがソケット操作を出し、pollフェーズのepoll_pwaitで応答を待っていました。
最後に
Vue Fes Japanという大きな舞台での登壇は初めてで、とても緊張しましたが、楽しかったです!登壇後は、Xや懇親会等で反応をいただけて嬉しかったです。
スライドを作る過程で、自分の理解も整理されました。ログを見ながら「fetch()が返すPromiseを解決するための処理が届く」と言い直す作業を繰り返したことで、イベントループとlibuvの役割分担を自分の言葉で説明できるようになりました。次はもう少し長い枠でも話してみたいと思います。
参考
- Vue Fes Japan 2026
- 検証一式(GitHub)- HasutoSasaki/vuefes-2026-await-strace
- Node.js の非同期処理をシステムコールから覗く - DevelopersIO
- Node.js の fetch を strace で追う - DevelopersIO
- 複数 fetch の直列 vs Promise.all を strace で比べる - DevelopersIO
- JS の非同期処理は epoll で成り立っているのか(Node.js / Deno / Bun)- DevelopersIO
- The Node.js Event Loop - Node.js
- epoll_wait(2) - Linux manual page







