Interactive
HTTP/2多重化可視化
多重化 vs HOLブロッキングタブでは、1本の遅いAPIリクエストと7本の速い静的アセットを同時に送るシナリオを、 HTTP/1.1(接続数1/2/6)とHTTP/2(多重化)それぞれの実際のスケジューリングで計算し、完了時間をウォーターフォールで比較できます。HPACKタブでは、3回連続リクエストのヘッダを静的テーブル・動的テーブル・リテラル送信という実際の判定ロジックで符号化し、 送信バイト数がリクエストを重ねるごとにどう減るかを確認できます。
1本の遅いAPIリクエスト(400ms)と7本の速い静的アセット(15〜40ms)を同時に送るシナリオです。HTTP/1.1は接続数ぶんだけ並列に処理できますが、各接続内では直列——同じ接続に割り当てられた速いリクエストは遅いリクエストの後ろで待たされます。
方式
api/data
400ms
style.css
30ms
app.js
40ms
logo.png
20ms
font.woff2
25ms
icon1.svg
15ms
icon2.svg
415ms
analytics.js
65ms
全リクエスト完了
415ms
最も割を食ったリクエスト
icon2.svg:本来15msで済むのに、実際は415ms(+400ms)かかった
接続数を1→2→6と増やすほど完了時間は縮みますが、HTTP/1.1である限り「たまたま遅いリクエストと同じ接続に割り当てられた」速いリクエストは待たされ続けます。HTTP/2は1本の接続の中でストリームを多重化するため、この待ちがそもそも発生しません——記事の言う「多重化は並列接続ではなく論理的な並列」の実例です。
すべてブラウザ内でスケジューリングとヘッダ符号化を実際に計算しています。実在のブラウザ・サーバー実装やネットワークは使っていません。
ここが分かる
- HTTP/1.1は接続を増やすほど速くなるが、接続数を超えるリクエストは必ずどこかで直列に詰まる——本来15msで済むはずの小さなリクエストが、たまたま遅いリクエストと同じ接続に割り当てられただけで400ms以上待たされる様子を実際の数値で確認できる。
- HTTP/2は1本の接続の中でストリームを多重化する「論理的な並列」——接続数に相当する制約が消えるため、遅いリクエストが1本混ざっていても他の全リクエストは自分の処理時間どおりに完了する。
- HPACKは静的テーブル(記事が明示する:method:GET=索引2、:path:/=索引4)→動的テーブル→リテラル送信の順で符号化する——2回目以降のリクエストで同じヘッダが1バイトの索引参照まで縮む様子を実測できる。
- 動的テーブルはRFC 7541が定義するとおり「name長+value長+32バイト」のサイズ計算とFIFO追い出しで実装——記事の「サイズ上限を超えると古いエントリから追い出される」という説明を実際のコードで確認できる。