もっと詳しい方のフォロー募集です
アプリケーションがマルチスレッドになってもネットワーク処理が分散されなければマルチコアを活かせない典型的な例です。id:viverの古橋さんがs100kpsとしてあげていた件にも近いかも。
memcachedで現象を確認します。最近のmemcachedはマルチスレッドで動くようになっているので、まずはそれを確認します。
$ memcached-tool localhost stats|grep threads
threads 4
スレッドが4つで起動しています。
負荷がそれなりにある状態(8000req/sec程度)で、コマンドラインでtopを開き、「1」キーを押して、CPUごとの使用率を表示します。(例はFedora8 kernel-2.6.23)
Tasks: 77 total, 1 running, 76 sleeping, 0 stopped, 0 zombie
Cpu0 : 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu1 : 3.0%us, 5.7%sy, 0.0%ni, 75.3%id, 0.0%wa, 7.7%hi, 8.3%si, 0.0%st
Cpu2 : 0.0%us, 0.3%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu3 : 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3692 nobody 20 0 10.9g 10g 716 S 10 44.0 10253:09 memcached
*メモリの行は削除しています。
CPUは4つ認識されていますが、CPU1しか使用されていないのがわかると思います。おそらく、CPU1のアイドルがなくなった時点で他のCPUに空きがあってもそれ以上の処理ができなくなります。なぜCPU1しか使われないかは「/proc/interrupts」をみるとなんとなくわかります。NICはBroadcom BCM5722です。
$ cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
0: 10569 0 10460 0 IO-APIC-edge timer
16: 301 301 302 303161 IO-APIC-fasteoi aerdrv, aerdrv, aerdrv, ioc0, eth0
17: 8 3570118309 7 7 IO-APIC-fasteoi eth1
memcachedの通信は主にeth1で行われるのですが、このeth1に関する割り込み処理がCPU1でしか行われていません。ソフトウェア割り込みはハードウェア割り込みが行われたCPUでしか行われないのもこの傾向を強めます。
マルチコアCPUの性能を活かすために考えられることは、ネットワークの割り込み処理を複数のCPUに分散することだと思うのですが、最新のNICにはRX/TX Multiple Queue(正式名称がわからない。Receive Side ScalingとかScalable I/O?)機能が備わっています。もともとRX/TX Multiple Queueは10GbpsのNICなどに備わっていた機能で、複数の割り込みチャンネルを持つことでネットワーク処理の分散を実現しています。最近のIntelやBroadcomの1GbpsのNICにも同じ機能があります。
以下はBroadcomのBCM5709を搭載しているマシンのinterrupts。(CentOS 5.3)
CPU0 CPU1 CPU2 .. CPUy CPUz
0: 342688765 0 0 0 0 IO-APIC-edge timer
114: 55 34 19613 39212 11 PCI-MSI-X eth0
122: 23 0 145 193 0 PCI-MSI-X eth0
130: 243 0 75 138 0 PCI-MSI-X eth0
138: 24 12 10423 35836 6 PCI-MSI-X eth0
146: 2141 0 110 556 0 PCI-MSI-X eth0
154: 21 4 12802 17806 7 PCI-MSI-X eth0
162: 561 0 216 72 0 PCI-MSI-X eth0
186: 72 76 97076 137548 197952 PCI-MSI-X eth1
194: 24 45478 100337 140189 554148 PCI-MSI-X eth1
202: 24 527452 94677 87876 305476 PCI-MSI-X eth1
210: 23 220400 175792 56390 205521 PCI-MSI-X eth1
218: 24 37023 30778 6169 11788 PCI-MSI-X eth1
226: 21 349792 48599 91969 0 PCI-MSI-X eth1
234: 23 206063 5911 43536 4 PCI-MSI-X eth1
*加工済み
こんな感じで、割り込み処理用のチャンネルが複数個存在して、CPU間で分散ができています。
まとめると、マルチコアCPU、SSDの普及によってハードウェアの性能があがり、epoll/kqueue/event portsによって大量のコネクションをさばけるようになると、こういった複数のCPUに分散できない処理がボトルネックになってくるので、最新のハードウェアとか対応しているカーネルを利用しようということです。