じゃあ、Linuxのネットワークスタックはどうなのん?

この記事の続きになる訳だが、いくらSolaris最強って言っても、大手メーカーがこぞってつつき回して性能改善したり機能追加したりしてるはずのLinuxで何も対策が打たれてない訳が無いよね。じゃあどうなってるんだろう、って話。

例によって、Linuxとか全ッ然知らないので、間違ってたらツッコミ下さい。

ポーリングとパケット処理のパス

殆どここで解説し尽くされてる。

Linuxにも動的ポーリングの実装(Solarisで言ってる動的ポーリングと同じものとは限らないが…)があって、NAPIとか呼ばれてるらしい。

NAPIを実装するドライバでは、こんな手順で受信処理を行ってる。

  • ハードウェア割り込みを受け、割り込みハンドラを起動
  • ハードウェア割り込みを禁止、ポーリングをスケジュール
  • ソフトウェア割り込み経由でNAPIのポーリングルーチンを起動
  • ドライバにポーリングを指示 この時、適切な性能を確保する為、一回のポーリングで取得する上限パケット数を指定する
  • ドライバのポーリングルーチンはデバイスのバッファからパケットを一つづつ取り出し順にTCP/IPスタックの受信ルーチンに渡していく
  • 上限パケット数に達したらポーリングを打ち切り、次のソフトウェア割り込み周期で再開する
  • バッファが空になったら、NAPIのポーリングを止め、ハードウェア割り込みを再開する

要するに、割り込み→割り込み禁止・ポーリング起動→バッファのパケットを食い尽くす→ポーリング停止・割り込み再開って感じかな。

これってSMPな場合、どうCPUが使われる?

ちゃんと読み込んでないので予想だけど。

ハードウェア割り込みを受けたCPUは割り込みハンドラを起動するけど、ここでは何もせずにポーリングをソフトウェア割り込みでスケジュールするはずで、ソフトウェア割り込み先のCPUを決め打ちするような事はしてないと思われるので、たまたまスケジューリング周期にソフトウェア割り込みを先に取ったCPUがポーリングを開始するはず→ソフトウェア割り込み経由でNAPIのポーリングルーチンが呼ばれる度にCPUがランダムに変わる?
訂正:
割り込み時にポーリングをスケジュールする際に呼ばれる__raise_softirq_irqoff()は、現在のCPUに対してソフトウェア割り込みをスケジュールしている。
なので、ソフトウェア割り込み先CPUは常にハードウェア割り込みが掛かったCPU。
例えそのCPUが凄く忙しくても。つまりこれで追記2で書かれてるような問題が起きるのかな。


ポーリングではバッファから取ったパケットをキューイングするのではなくて直にTCP/IPスタックを呼んで最後まで処理を完了させているように見えるので、バッファからパケットを取る所からTCP/IPスタックの最後まで同じCPUで一気に処理されるように見える。

追記:
参考資料追加〜。
OS-OMicron.org

とある素敵な新機能(RPS、RFS)

この辺に出てるけど、
Linuxカーネル2.6.35リリース、ネットワーク負荷軽減機構やH.264ハードウェアデコードなどをサポート | OSDN Magazine
Software receive packet steering [LWN.net]
rfs: Receive Flow Steering [LWN.net]
最近になってSMP環境でのTCP/IPスタックの性能向上の為の新機能が入ったらしくて、ちょっと調べてみた。

RPSが問題にしているのは、シングルキューなNICにおいてNAPIでのポーリング処理がper deviceでserializeされてる為に高負荷時にマルチキューなNICと比較して性能を出しにくく、また、シングルスレッドなのでCPUを増やしてもスケールしないという話らしい。

これを解決する為に、NAPIのポーリングで取り出したパケットを直接TCP/IPスタックに突っ込まずにCPU毎のキューを用意しここに突っ込み、ソフトウェア割り込みでスケジュールする。ターゲットCPUへの通知にはIPIを用いる。
これで今まで1つのCPUで処理してたパケット処理が複数CPUで行えるようになる。
単にランダムにパケットを振りまくと局所性の観点からイマイチなので、パケットのヘッダでハッシュを取り、この値を使ってCPUを決定する。同じ種類のパケットは常に同じCPUへ行く。

RFSはRPSに対する拡張で、RPSがパケットをキューイングするCPUを選ぶ時に、そのパケットをrecvmsgしようとしてるアプリケーションが走ってるCPUを選択するようにしたもの。これで更に局所性をあげようとしてる。

これらの拡張で、8コアCPUなマシンでのベンチマークスループットが最大2〜3倍にもなった。らしい。

ちなみに実装したのはGoogleの中の人。
プレゼンビデオがこのへんに。
Videos | Linux.com | The source for Linux information

追記2:
RPS,RFSが無いと悲しい目に遭うというお話。
The S100Kps problem(ソフト割り込み毎秒10万回問題) - sdyuki-devel
アプリケーションがマルチスレッドでもマルチコアCPUを活かせない件 - blog.nomadscafe.jp