ネットワーク I/O 限界の指標としてコンテキストスイッチ回数も使えるという話
Firebox X700X750e に FreeBSD を突っ込んで遊んでいたら、コンテキストスイッチで頭打ちになって面白かったのでメモ。
事の発端
B フレッツエクスプレスタイプなる、 GbE が家までやってくるという諸外国から見たら狂ってる感じの高速回線を自宅に引いた。それによりボトルネックとなった古い PC ルータを、手元にあった Firebox X700X750e でリプレースした。
出来上がったら当然ベンチマークしたくなったので、奈良とか調布とか堂島にある FreeBSD のミラーから、一斉に ISO image を fetch(1) で /dev/null に書き込むという、夜中じゃなかったら睨まれそうな方法にてベンチマークをして遊んでいた。
遊んでいる最中になにやら msk0 が発狂してしまったらしく、ベンチマーク中に突然 PPPoE がリンクダウンするという現象が発生、安定性のチェックを兼ねて sk0 に繋ぎ変えて PPPoE を張りベンチマークしたところ、トラフィックの傾向が変わったので詳細に調べてみた。
vmstat
こちらは mpd5 が作った netgraph ノードである ng0 の、繋ぐ先を sk0 に変更して、 3ホストから ftp ダウンロードを行い 18MB/s ぐらいでサチってしまっていたときの vmstat 1 の値。
cpu cs (context switch) は 25k強を推移している。さらに、割とバタついている。
procs memory page disks faults cpu r b w avm fre flt re pi po fr sr ad0 md0 in sy cs us sy id 0 0 0 119M 240M 0 0 0 0 0 0 0 0 2 127 323 0 1 99 0 0 0 119M 240M 0 0 0 0 0 0 0 0 2 126 303 0 2 98 0 0 0 119M 240M 0 0 0 0 0 0 0 0 2 119 306 0 1 99 0 0 0 119M 240M 0 0 0 0 0 0 0 0 259 183 786 0 3 97 0 0 0 119M 240M 0 0 0 0 0 0 0 0 1881 119 3658 0 10 90 0 0 0 119M 240M 0 0 0 0 0 0 0 0 6280 134 11657 0 21 79 0 0 0 119M 240M 0 0 0 0 0 0 0 1 14182 119 26491 0 33 67 0 0 0 119M 240M 0 0 0 0 0 0 0 0 14534 126 27786 0 29 71 0 0 0 119M 240M 0 0 0 0 0 0 0 0 13827 183 26191 1 31 68 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11844 119 22613 0 21 79 0 0 0 119M 240M 0 0 0 0 0 0 0 0 14785 127 28040 0 32 68 0 0 0 119M 240M 0 0 0 0 0 0 0 0 14669 126 27891 0 34 66 0 0 0 119M 240M 0 0 0 0 0 0 0 0 14676 126 28256 0 29 71 0 0 0 119M 240M 0 0 0 0 0 0 0 0 14631 186 27982 0 26 74 0 0 0 119M 240M 0 0 0 0 0 0 0 0 15270 142 29148 0 27 73 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11662 127 21984 0 27 73 0 0 0 119M 240M 0 0 0 0 0 0 0 1 11485 119 22065 0 26 74 0 0 0 119M 240M 0 0 0 0 0 0 0 0 14353 119 26953 0 37 63 0 0 0 119M 240M 0 0 0 0 0 0 0 0 15301 185 28774 1 33 66 0 0 0 119M 240M 0 0 0 0 0 0 0 0 15131 150 27906 0 41 59 0 0 0 119M 240M 0 0 0 0 0 0 0 0 14570 126 28052 0 36 64 0 0 0 119M 240M 0 0 0 0 0 0 0 0 14685 126 28099 0 36 64 0 0 0 119M 240M 0 0 0 0 0 0 0 0 15206 126 29013 0 26 74 0 0 0 119M 240M 0 0 0 0 0 0 0 0 13981 186 26355 0 35 65 0 0 0 119M 240M 0 0 0 0 0 0 0 0 15290 127 28847 0 40 60 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11376 119 21908 0 24 76 0 0 0 119M 240M 0 0 0 0 0 0 0 0 15816 119 29645 0 31 69 0 0 0 119M 240M 0 0 0 0 0 0 0 0 13791 184 26751 0 22 78 0 0 0 119M 240M 0 0 0 0 0 0 0 0 14903 146 28358 0 32 68 0 0 0 119M 240M 0 0 0 0 0 0 0 0 14870 127 28579 0 27 73 0 0 0 119M 240M 0 0 0 0 0 0 0 0 14606 119 27858 0 31 69 0 0 0 119M 240M 0 0 0 0 0 0 0 0 15422 126 29209 0 31 69 0 0 0 119M 240M 0 0 0 0 0 0 0 0 13878 183 26616 0 37 63 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12083 119 22919 0 26 74 0 0 0 119M 240M 0 0 0 0 0 0 0 0 15547 135 29154 0 38 63 0 0 0 119M 240M 0 0 0 0 0 0 0 0 13393 119 24476 0 38 63 0 0 0 119M 240M 0 0 0 0 0 0 0 0 15261 119 28270 0 38 63 0 0 0 119M 240M 0 0 0 0 0 0 0 0 13216 192 25424 0 26 74 0 0 0 119M 240M 0 0 0 0 0 0 0 0 14734 119 28039 0 31 69 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12785 127 24294 0 24 76 0 0 0 119M 240M 0 0 0 0 0 0 0 0 14702 126 27951 0 35 65 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12860 119 24887 0 21 79 0 0 0 119M 240M 0 0 0 0 0 0 0 0 13466 184 25632 1 34 65 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12884 119 24237 0 26 74 0 0 0 119M 240M 0 0 0 0 0 0 0 0 4873 127 9688 0 16 84 0 0 0 119M 240M 2 0 0 0 0 0 0 0 10735 124 20454 0 30 70 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12036 142 22767 0 23 77 0 0 0 119M 240M 0 0 0 0 0 0 0 0 4329 183 8684 0 9 91 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11835 119 22791 0 30 70 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11325 134 21168 0 29 71 0 0 0 119M 240M 0 0 0 0 0 0 0 0 4014 126 8120 0 11 89 0 0 0 119M 240M 0 0 0 0 0 0 0 0 6882 149 13300 0 20 80 0 0 0 119M 240M 0 0 0 0 0 0 0 0 4826 183 9627 0 16 84 0 0 0 119M 240M 0 0 0 0 0 0 0 0 9719 119 18418 0 25 75 0 0 0 119M 240M 0 0 0 0 0 0 0 0 13628 127 25634 0 24 76 0 0 0 119M 240M 0 0 0 0 0 0 0 0 3631 119 7307 0 12 88 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11749 119 22709 0 20 80 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12738 188 23873 1 31 68 0 0 0 119M 240M 0 0 0 0 0 0 0 0 13952 142 26133 0 37 63 0 0 0 119M 240M 0 0 0 0 0 0 0 0 3514 127 7036 0 8 92 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11792 126 22765 0 28 72 0 0 0 119M 240M 0 0 0 0 0 0 0 0 9377 119 17917 0 25 75 0 0 0 119M 240M 0 0 0 0 0 0 0 0 8100 183 15876 0 13 87 0 0 0 119M 240M 0 0 0 0 0 0 0 0 7964 119 15689 0 13 87 0 0 0 119M 240M 0 0 0 0 0 0 0 0 8850 134 17423 0 17 83 0 0 0 119M 240M 0 0 0 0 0 0 0 0 7863 119 15410 0 17 83 0 0 0 119M 240M 0 0 0 0 0 0 0 0 7894 126 15503 0 13 87 0 0 0 119M 240M 0 0 0 0 0 0 0 0 3961 184 7966 1 9 90 0 0 0 119M 240M 0 0 0 0 0 0 0 0 2 119 298 0 1 99 0 0 0 119M 240M 0 0 0 0 0 0 0 0 2 127 301 0 1 99 0 0 0 119M 240M 0 0 0 0 0 0 0 0 2 126 315 0 1 99
こちらは ng0 を繋ぐ先を msk2 に変更したときの vmstat 1 の出力。最大 35MB/s ぐらいでかっ飛んでいました。
コンテキストスイッチ回数は 24k前後で安定。
procs memory page disks faults cpu r b w avm fre flt re pi po fr sr ad0 md0 in sy cs us sy id 0 0 0 119M 240M 0 0 0 0 0 0 0 0 3 119 308 0 1 99 0 0 0 119M 240M 0 0 0 0 0 0 0 0 2 126 290 0 1 99 0 0 0 119M 240M 0 0 0 0 0 0 0 0 4 190 302 0 1 99 0 0 0 119M 240M 0 0 0 0 0 0 0 0 237 127 760 0 1 99 0 0 0 119M 240M 0 0 0 0 0 0 0 0 6684 119 12920 0 29 71 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12544 142 23829 0 46 54 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12645 119 23977 1 49 50 0 0 0 119M 240M 0 0 0 0 0 0 0 0 10196 186 19069 1 40 59 0 0 0 119M 240M 0 0 0 0 0 0 0 3 12599 127 24066 0 50 50 0 0 0 119M 240M 0 0 0 0 0 0 0 5 12326 119 23492 0 43 57 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12666 124 24348 0 39 61 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12734 119 24424 0 46 54 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12529 216 23920 0 49 51 0 0 0 119M 240M 0 0 0 0 4 0 1 0 12981 127 24810 0 51 49 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12718 149 24134 0 50 50 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12486 119 23533 0 45 55 0 0 0 119M 240M 0 0 0 0 0 0 0 0 10333 126 19010 0 40 60 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12700 207 23892 0 44 56 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11940 190 22923 0 42 58 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12275 119 24112 0 35 65 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12193 119 23718 0 36 64 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12542 126 24352 0 32 68 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12656 210 24283 0 46 54 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12307 127 23644 0 44 56 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12482 119 23847 0 48 52 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12594 119 24025 0 43 57 1 0 0 119M 240M 0 0 0 0 0 0 0 0 12601 158 24139 0 43 57 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12064 207 23248 0 43 57 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12171 127 24441 0 27 73 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12008 126 24246 0 31 69 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11978 119 24192 0 28 72 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11860 198 23824 0 27 73 0 0 0 119M 240M 0 0 0 0 0 0 0 0 12044 150 24050 0 23 77 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11865 127 23488 0 27 73 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11938 158 23457 1 23 76 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11870 119 23374 0 33 67 0 0 0 119M 240M 0 0 0 0 0 0 0 0 11423 184 22464 0 24 76 0 0 0 119M 240M 0 0 0 0 0 0 0 0 5902 142 11556 0 13 87 0 0 0 119M 240M 0 0 0 0 0 0 0 0 7151 127 13970 0 18 82 0 0 0 119M 240M 0 0 0 0 0 0 0 0 6434 119 12486 0 13 87 0 0 0 119M 240M 0 0 0 0 0 0 0 0 4990 119 9781 0 18 82 0 0 0 119M 240M 0 0 0 0 0 0 0 0 6689 222 13613 0 13 87 0 0 0 119M 240M 0 0 0 0 0 0 0 0 6289 119 12864 0 13 87 0 0 0 119M 240M 0 0 0 0 0 0 0 0 6617 157 13596 0 19 81 0 0 0 119M 240M 0 0 0 0 0 0 0 0 6099 142 12484 0 11 89 0 0 0 119M 240M 0 0 0 0 0 0 0 0 5852 126 11993 0 10 90 0 0 0 119M 240M 0 0 0 0 0 0 0 0 5514 183 11278 1 14 85 0 0 0 119M 240M 0 0 0 0 0 0 0 0 3829 119 7957 0 7 93 0 0 0 119M 240M 0 0 0 0 0 0 0 0 2 127 249 0 1 99 0 0 0 119M 240M 0 0 0 0 0 0 0 0 2 119 240 0 1 99 0 0 0 119M 240M 0 0 0 0 0 0 0 0 4 142 259 0 1 99
考察
cpu sy (system) は msk(4) を使ったときの方が高くなっているが、 cpu cs は逆に低下し、スループットは向上している。
Firebox X700X750e には sk(4) と msk(4) が 4つづつ付いている。後者の方がモダンで interrupt moderation (coalescence / throttling とも言う) を行うことが出来る。これにより msk(4) を使っていたときはコンテキストスイッチの発生が抑えられていた様子。
なお、その後何回か試していた所、最大 43MB/s ほど出た。そのとき CPU は 50% オーバーまで景気良く回っていた。
ちなみに、後述する sysctl をイジってコンテキストスイッチ回数を増やしてみたところ、大体 31k/s ぐらいまで振り切れて、スループットは 30MB/s 程度まで低下した。劣化の先にある限界は、この辺らしい。
sk(4) を使っている時はコンテキストスイッチ回数にバラつきがあったが、 duplicate ack がかなり出ていたので、短いタイムスパンで詰まったりしていそうである。
今後の展望
device polling とか使うと盛大に速くなるかもしれない。 polling(4) を参照。
なんか昔にイジった覚えがあるが、自宅サーバ復活させてなくて見れません。すみませんすみません。
http://www.muranet.jp/~mura/blosxom.cgi/bsd/samba-and-freebsd-tuning-3.html
他には、以下の sysctl をイジるとかも良いかもしれません。軽く触ったら悪化したりしたのでちゃんと見る必要がありそうですが。
inline# sysctl -a | grep holdoff dev.mskc.0.int_holdoff: 100 dev.mskc.1.int_holdoff: 100 dev.mskc.2.int_holdoff: 100 dev.mskc.3.int_holdoff: 100 inline# sysctl -a | grep process_limit dev.mskc.0.process_limit: 128 dev.mskc.1.process_limit: 128 dev.mskc.2.process_limit: 128 dev.mskc.3.process_limit: 128 inline#
msk(4) に PPPoE を高トラフィックで流すと、 "msk0: watchdog timeout" とか言い残して刺さる件は、 TSO とかを切って様子見ですかね…。内側 I/F は無事とは言え地味に困る…。
参考情報
動かしていたのは FreeBSD 8.2 + mpd5 という、速い PPPoE 箱を自作するときの定番構成。
ハードウェアは Celeron M 1.3GHz に 512MB RAM と、 32bit PCI を共有する sk(4) が 4つ、 PCI-E 接続の msk(4) が 4つという構成。
FreeBSD をよく使っていないと mpd5 が使う netgraph を知らないと思いますが、非常に興味深いものなのでググって頂くと吉。誤解を恐れずに言うならば kernel 内のネットワークスタックを柔軟に繋ぎかえるフレームワークのようなもの、と言う感じ。
netgraph は kernel 内で完結しているので、 mpd5 によって netgraph で PPPoE することで、 userland PPPoE で起きるオーバーヘッドを回避することが出来る。いや、 OpenBSD みたいに pppoe(4) とかある方が分かりやすいとは思いますが。