Nginxのhttp2_streams_index_sizeパラメータについて

Nginxのhttp2の設定項目にhttp2_streams_index_sizeがある。直感的には分かりにくかったのでちょっと調べる。


そのほかのパラメータは過去に書いたとおり、「Nginx 1.9.4 HTTP/2パッチのconf パラメータ設定項目

streams_index配列

各ストリームに関する情報はngx_http_v2_node_s構造体によって管理されています。例えばストリームID(sid)、weight、parentといった情報を持ちます。


このngx_http_v2_node_s構造体の配列がstreams_indexです。streams_index配列は、ストリームIDからそのストリームを管理しているngx_http_v2_node_s構造体を探すのに使用されます。


http2_streams_index_sizeはこの配列の長さを指定します。


例えばhttp2_streams_index_sizeに「8」を指定した場合は図のようになります。



図のように長さ8の配列によってストリームが管理されます。ハッシュ法(チェイン法)であり、同じインデックスに属するストリームは、イデックス毎にリスト構造になります。


格納されるインデックスは、ストリームIDを元に算出されます。

index = (sid >> 1) & (http2_streams_index_size - 1)

例えば、http2_streams_index_sizeが8の場合では、ストリームID:19のインデックスは1になります。

ngx_http_v2_get_node_by_id

次に、streams_indexの使われ方を確認します。
streams_indexはngx_http_v2_get_node_by_id関数で使用されます。ngx_http_v2_get_node_by_idは指定されたストリームIDから、一致するngx_http_v2_node_sを探す関数です。(また、無かった場合に追加する場合もあります。)


このngx_http_v2_get_node_by_idはHEADERSフレームを受信した際に新しくstreams_indexに追加する際や、PRIORITYフレームにより依存ストリームをセットする際、WINDOW_UPDATEフレームによりWindowサイズが変更される際、などに呼び出されます。


そのたびに、streams_indexを用いて指定されたストリームIDを探索します。
探索のおおまかな流れはストリームIDより、格納されているstreams_indexのインデックスを参照する。無ければ、リストを順々にたどっていきます。

http2_streams_index_size

さて大体の概要が分かった所で、http2_streams_index_sizeの設定について考察します。


考慮するポイントとしては以下の二点になるかと思います

  • streams_indexが短いと各インデックスのリストが長くなり、探索時に辿る処理が多くなる
  • streams_indexは接続初期時に確保されるため、コネクション毎に初期確保するメモリが増える
  • http2_max_concurrent_streamsを下げれば、見つかる場合はリストを辿る距離は短くなるはず。(見つからない場合はリストを最後まで辿る)


あんまり頑張ってチューニングする必要はないと思う。


個人的には探索のコストはあまり気にしなくて良いと思う...
いくつか試してみたが、1,2,4はやはり少なすぎる、128や増やしてもあまり効果は薄そう。やはり32前後が一番よさそう。
よっぽどメモリがきになるようであれば、デフォルトの32より減らすとかあるかもしれない?