マルチコアとネットワークスタックの高速化技法

69
マルチコアとネットワー クスタックの高速化技法 @syuu1228 13423日火曜日

Upload: takuya-asada

Post on 30-Nov-2014

8.679 views

Category:

Documents


2 download

DESCRIPTION

 

TRANSCRIPT

マルチコアとネットワークスタックの高速化技法

@syuu1228

13年4月23日火曜日

はじめに

• ネットワークの高速化に伴ってハード・ソフト両面でネットワークIO

の実装が繰り返し見直されてきている

• これがOSの実装にも大きく影響

13年4月23日火曜日

NIC性能の急激な向上

• NIC:1GbE→10GbE

• CPU:1GHz→3.2GHz

• メモリ:CPUの1/10のペース→CPUやメモリの速度がネットワークIOのボトルネックに

13年4月23日火曜日

マルチコアCPUの普及

• コア数は増えていっている

• 1コアあたりの性能は不足→ネットワークIOをマルチスレッドで処理する必要が出てきた

13年4月23日火曜日

今日のお題

1. 割り込み頻度の問題

2. オフローディング

3. データ移動に伴うオーバヘッド

4. プロトコル処理の並列化

13年4月23日火曜日

ちょっとおさらい

13年4月23日火曜日

Network stack in 4.3BSD

Process(User)

Process(Kernel)

HW Intr Handler

SW Intr Handler

パケット受信

プロトコル処理

ソケット受信処理

ユーザプログラム

user buffer

inputqueue

socketqueue

パケット

システムコール

プロセス起床

ソフトウェア割り込みスケジュール

ハードウェア割り込み

ユーザ空間へコピー

13年4月23日火曜日

1. 割り込み頻度の問題

13年4月23日火曜日

割り込みが多すぎるProcess(User)

Process(Kernel)

HW Intr Handler

SW Intr Handler

パケット受信

プロトコル処理

ソケット受信処理

ユーザプログラム

user buffer

inputqueue

socketqueue

パケット

システムコール

プロセス起床

ソフトウェア割り込みスケジュール

ハードウェア割り込み

ユーザ空間へコピー

13年4月23日火曜日

割り込みが多すぎる

• 割り込みの頻度が高すぎて、他の処理の実行が阻害される

• 割り込みに伴うコンテキスト切り替えのコストが高い

13年4月23日火曜日

Interrupt Coalescing

• ハードウェアでの対応

• パケット数個に一回割り込む、或いは一定期間待ってから割り込む

• 割り込みを間引く

• デメリット:レイテンシが上がる

13年4月23日火曜日

Interrupt Moderation on ixgbe(4)

• hw.ixgbe.enable_aim流量に応じ動的に割り込み頻度を調整

• hw.ixgbe.max_interrupt_rate割り込み頻度を指定

• hw.intr_storm_threshold割り込みが多すぎると警告が出るようになっているので、警告上限を上げる必要がある

13年4月23日火曜日

Interrupt Moderationを切ってみる

• Linux, ixgbeで実験

• modprobe ixgbe InterruptThrottleRate=0,0

• iperf -s / iperf -c <IP>

• 24000 - 31000 interrupts/sec for 1CPU(これでも後述のハイブリッド方式の為、ソフト的に割り込み抑制をかけている)

13年4月23日火曜日

どれくらいの頻度に設定されているのか

• 10GbEだと頻度が低すぎてもバッファ溢れやレイテンシ増大の原因になる

• Linuxのe1000eやixgbeでは8000

interrupts/secがデフォルトの閾値(但し最新のixgbeだと動的調整がデフォルトになっている)

13年4月23日火曜日

Polling

• ソフトウェアでの対応

• NICの割り込みを無効化

• タイマーを使って定期的にNICのレジスタをポーリング、パケットが有ったら受信処理

• デメリット

• タイマー周期分のレイテンシが発生

• タイマー割り込み間隔を上げるとオーバヘッドが増大

13年4月23日火曜日

polling(4)• options DEVICE_POLLING

options HZ=1000

• sysctl kern.polling.enable=1sysctl kern.polling.user_frac=50

• CPUが遅い場合は効果がある

• 後述のマルチキューNICに非対応HZ=1000程度では10GbEには不足→新しいサーバには不向き

13年4月23日火曜日

ハイブリッド方式• ソフトウェアでの対応

• 通信量が多く連続してパケット処理を行っている時のみ割り込みを無効化、ポーリングで動作

• Ringバッファからパケットが無くなったら割り込みを有効化

13年4月23日火曜日

netisr direct dispatch

• LinuxのNAPIと同様

• 割り込みコンテキストから直接プロトコル処理を実行

• Ringバッファにパケットがある間、NICの割り込みを禁止

• Ringバッファが空になったら割り込み再開

Process(User)

Process(Kernel)

HW Intr Handler

パケット受信

プロトコル処理

ソケット受信処理

ユーザプログラム

user buffer

socketqueue

パケット

システムコール

プロセス起床

ハードウェア割り込み

ユーザ空間へコピー

13年4月23日火曜日

Low latency interrupt

• ハードウェアでの対応

• Interrupt Coalescingを行った結果レイテンシが増大

• 低レイテンシで処理したいパケットを判別Coalescingを無視して即時割り込み

13年4月23日火曜日

LLI on ixgbe

• 以下のようなフィルタで即時割り込みするパケットを指定

• 5-tuple(protocol, IP address, port)

• TCP flags

• frame size

• Ethertype

• VLAN priority

• FCoE packet

• 但しFreeBSDのixgbeドライバでは非サポート

13年4月23日火曜日

2. オフローディング

13年4月23日火曜日

プロトコル処理が重いProcess(User)

Process(Kernel)

HW Intr Handler

SW Intr Handler

パケット受信

プロトコル処理

ソケット受信処理

ユーザプログラム

user buffer

inputqueue

socketqueue

パケット

システムコール

プロセス起床

ソフトウェア割り込みスケジュール

ハードウェア割り込み

ユーザ空間へコピー

13年4月23日火曜日

プロトコル処理が重い

• 特に小さなパケットが大量に届く場合にプロトコル処理でCPU時間を大量に使ってしまう

13年4月23日火曜日

TOE(TCP Offload Engine)

• NIC上のTCP/IPスタックへプロトコル処理をフルオフロード

• デメリット

• セキュリティ:TOEにセキュリティホールが生じても、OS側から対処が出来ない

• 複雑性:OSのネットワークスタックをTOEで置き換えるにはかなり広範囲の変更が必要メーカによってTOEの実装が異なり、TOE用の共通APIを作るのが困難OSのプロトコル処理をバイパスするのでパケットフィルタと相性が悪い

• 対応NICは少ない

13年4月23日火曜日

toecore

• Chelsio 10GbEのみサポート

• options TCP_OFFLOAD

• ifconfig cxgbe0 toe

• カーネルはmbuf↔アプリ間のデータコピーのみを行い、プロトコル処理はNIC

が行う

13年4月23日火曜日

TOEよりも更に丸投げ• iWARP

NICによるゼロコピー通信(RDMA)のサポートInfiniBandと同じインタフェースでリモートノードへアクセス通信にはTCP/IPが使われているが、NICがプロトコルを喋る

• iSCSI・FCoE

OSに対してはSCSIコントローラのように振る舞うNICがiSCSI・FCoEプロトコルを喋る

13年4月23日火曜日

Checksum Offloading

• IP・TCP・UDP checksumの計算をNICで行う

• フルオフローディングと異なりOSでの対応が容易

13年4月23日火曜日

FreeBSDでのChecksum Offloading

• ifconfig -m ix0|grep capabilitiesどんな種類のchecksum offloadingをサポートしているか確認

• ifconfig ix0 rxcsum txcsum rxcsum6 txcsum6checksum offloadingの有効化

• TOEと異なり多くのNICが対応している

13年4月23日火曜日

Checksum Offloadはどれくらい性能に影響するのか

• Linux, ixgbeで実験

• ethtool -K ix0 rx off

• iperf -s / iperf -c <IP>

• 有効:7.99 Gbits/sec

• 無効:6.66 Gbits/sec

13年4月23日火曜日

Large Segment Offload(TCP Segmentation Offload)

• パケット送信時の分割処理をNICへオフロード

• OSはパケット分割処理を省略出来る

13年4月23日火曜日

FreeBSDでのLarge Segment Offload

• ifconfig -m ix0|grep capabilitiesTSO4が表示されていればTCPv4

TSO6が表示されていればTCPv6のLSOに対応

• ifconfig ix0 tso4 tso6Large Segment Offloadの有効化

• カーネルからはMTUサイズがとても大きなNICへパケットを送信しているように見える

13年4月23日火曜日

Large Segment Offloadはどれくらい性能に影響するのか

• Linux, ixgbeで実験

• ethtool -K ix0 tso off

• iperf -s / iperf -c <IP>

• 有効:8.96 Gbits/sec

• 無効:9.00 Gbits/sec

13年4月23日火曜日

Large Receive Offload

• LSOの逆

• 受信パケットをNIC上で結合1つの大きなパケットとしてOSへ渡す

• プロトコルスタックの呼び出し回数が少なくて済む

13年4月23日火曜日

FreeBSDでのLarge Receive Offload

• ifconfig -m ix0|grep capabilitiesLROが表示されていれば対応

• ifconfig ix0 lroLarge Receive Offloadの有効化

• カーネルからはMTUサイズがとても大きなNICからパケットが送られてきているように見える

13年4月23日火曜日

Large Receive Offloadはどれくらい性能に影響するのか

• Linux, ixgbeで実験

• ethtool -K ix0 lro off

• iperf -s / iperf -c <IP>

• 有効:8.03 Gbits/sec

• 無効:7.84 Gbits/sec

13年4月23日火曜日

LSO・LROのSW実装• LinuxではLSO・LROをソフトウェアで実装している

• オフロードではなくソフトウェア処理でも、結果的にプロトコルスタックの実行回数が減るならば性能が上がる余地がある

• FreeBSDはHWのみの対応

13年4月23日火曜日

3. データ移動に伴うオーバヘッド

13年4月23日火曜日

TOEがネットワークIOパフォーマンスの解決策か?

• 大きなパケット(>8KB)を用いるデータベースサーバなどのユースケースならTOEは有効→より小さなパケットの多い他のサーバにはあまり有効でない

• iWARPやiSCSI HBAなどのオフローディング方式では既存のアプリを載せられない

• ローエンドなNICのTOEエンジンは新しいXeonよりずっと遅い→オフロードする事でかえってパフォーマンスが落ちる事もありえる

13年4月23日火曜日

どの処理が重いのか

• プロトコル処理よりもむしろNIC・メモリ・CPUキャッシュの間でのデータ移動に伴うオーバヘッドの方が重いケースがある

• 特にメモリアクセスが低速

13年4月23日火曜日

• NICのバッファ→アプリケーションのバッファへパケットをDMA転送

• CPU負荷を削減

• チップセットに実装

• (Intel I/O ATとも呼ばれる)

Intel QuickData Technology

13年4月23日火曜日

Intel QuickData Technology

Process(User)

Process(Kernel)

HW Intr Handler

SW Intr Handler

パケット受信

プロトコル処理

ソケット受信処理

ユーザプログラム

user buffer

inputqueue

socketqueue

パケット

システムコール

プロセス起床

ソフトウェア割り込みスケジュール

ハードウェア割り込み

ユーザ空間へコピー

13年4月23日火曜日

Intel QuickData Technology

• FreeBSDでは非対応

13年4月23日火曜日

Intel Data Direct I/O Technology

• 従来、NICはメモリにパケットを書き込み、CPUはメモリからキャッシュにパケットを読み込んでからアクセスしていた

• DDIOではNICがCPUのキャッシュへDMAを行えるようにする→メモリアクセス分のレイテンシを削減

• 新しいXeonと10GbEでサポート

• OS側での対応は不要な模様

13年4月23日火曜日

4. プロトコル処理の並列化

13年4月23日火曜日

旧型のプロトコルスタックではマルチスレッドで処理できない

Process(User)

Process(Kernel)

HW Intr Handler

SW Intr Handler

パケット受信

プロトコル処理

ソケット受信処理

ユーザプログラム

user buffer

inputqueue

socketqueue

パケット

システムコール

プロセス起床

ソフトウェア割り込みスケジュール

ハードウェア割り込み

ユーザ空間へコピー • システムに1つしかない受信キュー

• 並列化されていないソフトウェア割り込みハンドラ

13年4月23日火曜日

FreeBSD network stackのマルチスレッド対応

• 3つの処理方式を実装• マルチスレッド化されたランキューに積んでスケジュールする方式

• direct dispatch(その場でプロトコル処理)

• ハイブリッド

13年4月23日火曜日

マルチスレッド化されたランキューに積んでスケジュールする方式• net.isr.dispatch = deferred

net.isr.maxthreadsnet.isr.bindthreads

• プロトコル処理用のワーカースレッドを任意の数起動できる

• スレッドごとに受信キューを持つ

• スレッドはCPUに固定する事も、通常のプロセス同様にマイグレートされるように設定する事も可能

13年4月23日火曜日

送り先スレッドの選択方法は?

• プロトコル毎にポリシー(NETISR_POLICY_*)とハンドラ関数で設定されている

• イーサーネットならNETISR_POLICY_SOURCE→NICによってスレッドを決定

13年4月23日火曜日

direct dispatch

• net.isr.dispatch = direct

• 常に割り込みコンテキストでプロトコル処理

13年4月23日火曜日

ハイブリッド

• net.isr.dispatch = hybrid

• deferredと基本的に同じように動作しようとするが、宛先スレッドが自CPUのものだったらdirect dispatchする

13年4月23日火曜日

それでも1つのNICからのパケットは1つのCPUで処理される• 1つのNICは1つの割り込みしか持たない

• 受信処理の途中でパケットを複数のコアに割り振る仕組みがない→ NICが複数あって割り込み先CPUが分散されていれば並列に処理されるが、1つのNIC

からのパケットは1つのCPUで処理される

13年4月23日火曜日

でも…

• ネットワークIO負荷が高いと1コアでは捌き切れなくなってくるケースがある

• その場合、アイドルなコアがあるのに1コアだけカーネルが8~9割のCPU時間を食ってしまい、アプリの性能が落ちるという現象が発生

• 1つのNICに届いたパケットを複数のコアに分散して処理したい

13年4月23日火曜日

MSI-X割り込み• PCI Expressでサポート

• デバイスあたり2048個のIRQを持てる

• それぞれのIRQの割り込み先CPUを選べる→1つのNICがCPUコア数分のIRQを持てる

13年4月23日火曜日

ランダムにパケットを分散すれば良いのか?

• 複数コアで1つのNICに届いたパケットを並列に受信処理を行うと到着順と異なる順序でプロセスに渡される可能性がある(CPU間で待ち合わせを行わない限りどんな順で処理が終わるかは保証できない)

• UDPには順序保証が無いので問題ない

• TCPには順序保証が有るので並列に処理されるとパケットの並べ直し(リオーダ)が発生してパフォーマンスが落ちる

• 1つのフローのパケットがバラバラのコアで処理されると、キャッシュ競合が増えて性能が落ちる可能性がある

13年4月23日火曜日

Receive Side Scaling

• (Multi Queue NICとも呼ばれる)

• パケットヘッダのハッシュ値を元にパケットを複数の受信キューへ振り分け→同一フローは同じキューへ

• 振り分け先キューはハッシュテーブルの値に基づく

• 受信キューはそれぞれIRQを持ち、別々のCPUへ割り込む(キュー数がコア数より少ない事もある)

13年4月23日火曜日

Receive Side Scaling

NIC

パケットパケットパケット

ハッシュ計算

パケット着信

hash queue

ディスパッチ参照

RX Queue

#0

RX Queue

#1

RX Queue

#2

RX Queue

#3

cpu0 cpu1 cpu2 cpu3

受信処理

割り込み

受信処理

■■

01

13年4月23日火曜日

MultiQueue NIC on FreeBSD (dmesg)

igb5: <Intel(R) PRO/1000 Network Connection version - 2.0.7> port

0x1000-0x101f mem 0xb2400000-0xb241ffff,0xb1c00000-0xb1ffffff,0xb2440000-

igb5: Using MSIX interrupts with 9 vectors

igb5: [ITHREAD]

igb5: [ITHREAD]

igb5: [ITHREAD]

igb5: [ITHREAD]

igb5: [ITHREAD]

igb5: [ITHREAD]

igb5: [ITHREAD]

igb5: [ITHREAD]

igb5: [ITHREAD]

igb5: Ethernet address: 00:1b:21:81:e9:57

MSI-Xによって複数の割り込みベクタが確保されている

13年4月23日火曜日

MultiQueue NIC on FreeBSD (vmstat -i)

# vmstat -i | grep ix0

irq256: ix0:que 0 3555342 10305

irq257: ix0:que 1 3120223 9044

irq258: ix0:que 2 3408333 9879

irq259: ix0:que 3 3279717 9506

irq260: ix0:link 4 0

キュー毎にIRQが割り当てられている13年4月23日火曜日

受信キューの割り当て

• フローに割り当てられたキューが宛先プロセスのCPUと異なるとオーバヘッドが発生する

CPU0 CPU1 CPU2 CPU3

割り込みハンドラ

ネットワークスタック

プロセス起床

プロセスA

キュー2

ネットワークスタック

プロセス起床

プロセスB

割り込みハンドラ

キュー3

13年4月23日火曜日

受信キューの割り当て

• ハッシュテーブルの設定値を変更する事でCPUを一致させる事ができる

CPU0 CPU1 CPU2 CPU3

割り込みハンドラ

ネットワークスタック

プロセス起床

プロセスA

バッファ

ネットワークスタック

プロセス起床

プロセスB

割り込みハンドラ

バッファ

13年4月23日火曜日

Receive Side Scalingの制限• 例えばIntel 82599 10GbE Controllerだと:

• Redirection Tableは128エントリ

• ハッシュ値は下位4bitのみ使用

• フローが多いとハッシュ衝突する為、特定フローを特定CPUへキューするのにはあまり向いていない

13年4月23日火曜日

Intel Ethernet Flow Director(ixgbe)

• フローとキューの対応情報を完全に記録• 32kのハッシュテーブルの先にリンクドリスト

• 2つのFilter mode

• Signature Mode:ハッシュ値→最大32k個

• Perfect Match Mode:ヘッダの完全マッチ(dst-

ip, dst-port, src-ip, src-port, protocol)→最大8k個

13年4月23日火曜日

Intel Ethernet Flow Directorのフィルタ更新方法

process

送信処理

システムコール

ソケット

プロトコルスタック

ドライバ

Txq

NIC

フィルタ更新

Flow DirectorFilters

プロセスコンテキストからのパケット送出時に送信元CPUとパケットヘッダを用いてフィルタを更新

13年4月23日火曜日

Intel Ethernet Flow Director on FreeBSD

• ixgbeのドライバはデフォルトでFlow

Directorを有効にしている

13年4月23日火曜日

RPS(Linux)• RSS非対応のオンボードNICをうまくつかってサーバの性能を向上させたい

• ソフトでRSSを実装してしまおう

• ソフト割り込みの段階でパケットを各CPUへばらまく

• CPU間割り込みを使って他のCPUを稼動させる

• RSSのソフトウエアによるエミュレーション

13年4月23日火曜日

cpu3cpu2cpu1cpu0

割り込み無効化

プロトコル処理

ソケット受信処理

ユーザプログラム

user buffer

socketqueue

パケット

システムコール

プロセス起床

ハードウェア割り込み

ユーザ空間へコピー

パケットパケット

ソフトウェア割り込み

パケット受信

ハッシュ計算

ディスパッチ

プロトコル処理

ソケット受信処理

ユーザプログラム user

buffer

socketqueue

backlog#1

hash queue 参照■■

01

CPU間割り込み

backlog#2

backlog#3

13年4月23日火曜日

RFS(Linux)

• 受信待ちプロセスがいるCPUへパケットをディスパッチ出来る仕組みをRPSに追加

• データローカリティの向上、レイテンシの削減

13年4月23日火曜日

RPS/RFS for FreeBSD

• GSoC’11 by Kazuya GODA

• マージされていないが実装済ベンチマークで性能が向上する事を確認

13年4月23日火曜日

まとめ• 高速なネットワークIOを捌くために様々な改善が行われている事を紹介

• ハードウェア・ソフトウェアの両面で実装の見直しが繰り返し要求されており、その範囲はネットワークに直接関係ないような所にまで及ぶ

• 取り敢えず明日から出来ること:まずはサーバに取り付けるNICを選ぶときに「マルチキューNIC」「RSS対応」などとされているものを選ぼう

13年4月23日火曜日