Red Had Linux を搭載した 16 コアの NUMA マシンで Java プログラムのベンチマークを行いました。Java DatagramSocket (UDP 用) のスループットを、1 秒間に送受信できる (64 バイト サイズの) パケット数で測定しました。このプログラムは、単一のソケットと、ソケットをリッスンする n 個のスレッドで構成されていました。パケットが到着すると、ペイロードを byte[] 配列にコピーし、その配列を使用して新しい DatagramPacket を作成し、元の場所にすぐに送り返します。UDP 層での ping と考えてください。
複数のスレッド (2 つまたは 4 つなど) を使用すると、Java DatagramSocket ソケットのスループットが大幅に低下することがわかりました。ソケットをリッスンするために 1 つのスレッドのみを使用すると、1 秒あたり 122,000 パケットのスループットが達成されますが、複数のスレッドでは 1 秒あたり 65,000 パケットしか達成されません。これで、NUMA マシンの任意のコアでスレッドが実行される可能性があり、メモリがあるノードから別のノードに移動する必要がある場合、メモリ アクセスが高価になることがわかりました。ただし、2 つのスレッドがある場合、「間違った」コアで実行されるのは 1 つだけで、もう 1 つのスレッドは依然として非常に高いスループットを達成するはずです。もう 1 つの考えられる原因は、Datagramsocket の同期の問題ですが、これらは推測にすぎません。本当の説明が何であるかについて、誰かが良い洞察を持っていますか?
このプログラムを複数のポートで複数回 (並行して) 実行すると、全体的なスループットが向上することがわかりました。1 つのスレッドでプログラムを 4 回開始し、各プログラムは別々のポート (5683、5684、5685、および 5686) でソケットを使用しました。4 つのプログラムの合計スループットは、1 秒あたり 370,000 パケットでした。要約すると、同じポートで複数のスレッドを使用するとスループットが低下し、1 つのスレッドで複数のポートを使用するとスループットが向上します。これはどのように説明できますか?
システム仕様:
ハードウェア: 2 つの AMD Opteron(TM) プロセッサ 6212 プロセッサ上の 16 コアは、それぞれ 32 GB RAM を備えた 4 つのノードで構成されています。周波数: 1.4 Ghz、2048 KB キャッシュ。
node distances:
node 0 1 2 3
0: 10 16 16 16
1: 16 10 16 16
2: 16 16 10 16
3: 16 16 16 10
OS は Red Hat Enterprise Linux Workstation リリース 6.4 (Santiago) で、カーネル バージョンは2.6.32-358.14.1.el6.x86_64
. Java バージョン"1.7.0_09"
、Java(TM) SE ランタイム環境 ( build 1.7.0_09-b05
)、Java HotSpot(TM) 64-Bit Server VM ( build 23.5-b02, mixed mode
)、および-XX:+UseNUMA
フラグを使用しました。サーバーとクライアントは 10GB イーサネットで接続されています。