Linux ソケットバッファのチューニング

ADSLや光回線などの充実によって、ここ数年でネットワークの回線速度もかなり進歩してきました。しかし、Linuxの バージョンによっては、一昔のネットワーク速度を基準としてパラメータの設定を行っているためにネットワーク帯域をフル活用できない場合もあります(特に、1Gbps を超えるような場合はその可能性が高い)。そこで、今回はボトルネック の一つとなりやすいバッファサイズのチューニング方法について記述します。

sysctl 変数の設定

Linuxにおいてシステム全体のバッファサイズを変更する場合には sysctl コマンドを使用します。設定する項目は、下記の9種類です(Manpage of TCP 参照)。

net.ipv4.tcp_window_scaling
RFC 1323 の TCP ウィンドウスケーリングを有効にします。この機能を用いると(接続先が対応していれば) TCP 接続で 64 KByte 以上のウィンドウが使えるようになります。送受信バッファサイズを 64 KByte 以上に設定した場合、そのバッファを有効に利用できるようにこのオプションを有効にしておきます。

net.ipv4.tcp_rmem
TCP が受信バッファサイズを調整するために用いられます。この sysctl 変数は [min,default,max] の 3 種類の値を持ちます。それぞれの値の意味は下記の通りです。

  • min … 各 TCP ソケットが用いる受信バッファの最小値です。この値は SO_RCVBUF を用いてソケットの最低受信バッファサイズを宣言する際には用いられません。
  • default … TCP ソケットの受信バッファのデフォルト値です。この値は net.core.rmem_default よりも優先されます。
  • max … 各 TCP ソケットが用いる受信バッファの最大値です。この値よりも net.core.rmem_max が優先されます。この値は SO_RCVBUF を用いてソケットの受信バッファサイズを制限する際には用いられません。

net.ipv4.tcp_wmem
TCP が送信バッファサイズを調整するために用いられます。この sysctl 変数も [min,default,max] の3つの値を持ちます。それぞれの値の意味は net.ipv4.tcp_rmem と同様です。

net.ipv4.tcp_mem
TCP がメモリ使用量を追跡するために用いられます。この sysctl は [low,pressure,high] の3つの値を持ちます。それぞれの値の意味は下記の通りです。

  • low … TCP は、グローバルに割り当てたメモリがこの数値以下の場合、メモリアロケーションを調整しません。
  • pressure … TCP がアロケートしたメモリがこの数値を越えると、TCP はメモリ消費を抑えるようになります。
  • high … TCP がグローバルに割り当てるメモリの最大値です。

net.core.rmem_default
net.ipv4.tcp_rmem の default と同様です。ただし、net.ipv4.tcp_rmem の default の方が優先されます。

net.core.wmem_default
net.ipv4.tcp_wmem の default と同様です。ただし、net.ipv4.tcp_wmem の default の方が優先されます。

net.core.rmem_max
net.ipv4.tcp_rmem の max と同様です。ただし、設定値はこちらの方が優先されます。

net.core.wmem_max
net.ipv4.tcp_wmem の max と同様です。ただし、設定値はこちらの方が優先されます。

net.core.optmem_max
補助バッファの最大サイズを表します。

Example

以下に、バッファサイズの変更例を記述します。設定するバッファサイズは、帯域遅延積などを考慮して決定して下さい。

sysctl -w net.ipv4.tcp_window_scaling=1
sysctl -w net.ipv4.tcp_rmem="4096 873800 1747600"
sysctl -w net.ipv4.tcp_wmem="4096 873800 1747600"
sysctl -w net.ipv4.tcp_mem="2048000 2048000 2048000"
sysctl -w net.core.rmem_default=873800
sysctl -w net.core.wmem_default=873800
sysctl -w net.core.rmem_max=1747600
sysctl -w net.core.wmem_max=1747600
sysctl -w net.core.optmem_max=20480

その他

設定したバッファサイズがきちんと適用されているかどうかは、Iperf などを用いて確認すると良いと思います。Iperf では、データ転送を開始するとコンソールにバッファサイズが表示されるので便利です。