通常、アプリケーションの実行に使用されるCPUやコアを指定するのはオペレーティングシステムです。 アプリケーションが必要とするスレッド数と他のアプリケーションにより、OSは必要に応じてスレッドを移動させ、各CPUの全体的な負荷を均衡させます。 CPUよりスレッドの数が多いい場合(標準)、OSはCPUを複数のスレッド間で共有します。つまり、各スレッドは実行されるまで一時停止されます。 アプリケーションによっては、この方法が正しく動作しないことがあり、特定のCPUやCPUグループを指定のアプリケーションに制限させると便利です。 ほとんどのOSプラットフォームで一つのプロセスが特定のCPU上でのみ実行されるように指定できます。 これは、一般的に、CPUアフィニティ、若しくはCPUピニングと呼ばれます。

アプリケーションに特定のCPUを割り当てることで常にCPUリソースが十分に確保される方法です。 逆に、同じマシン上で実行される他のプロセスに十分なリソースを保証するために、いくつかのプロセッサを明示的に使用せず、待機させることができます。 プロセッサアフィニティを設定することで、CPUキャッシュを大幅に最適化することもできます。 つまり、プロセスがCPUを変更するたびに、そのデータがあるCPUから別のCPUに転送されます。 この転送にはコストがかかりますが、限られた数のCPUにプロセスを固定することで最小限に抑えることができます。 ただし、使用可能な時にアプリケーションが異なるCPUで並列タスクを実行することもありますので、十分なプロセッサを使用できるよう、設定する注意が必要です。

残念ながら、Javaはコア若しくはプロセッサの親和性でJVMを起動するソリューションを提供していません。 Javaアプリケーションを特定のCPUに固定する必要がある場合は、procafftasksetinvoke native codeなどのコマンドを使用する必要があります。 Processor affinity これらのソリューションはプラットフォーム特有です。

解決!

Java Service Wrapper プロフェッショナル版は、コードを書かかずCPUアフィニティを統一的で簡単に設定できるようにすることで、この問題に対処しています。 Wrapper バージョン 3.5.27まで、WindowsとLinuxしかサポートされていませんが、近来リリースにも他のプラットフォームをサポートする予定です。

この設定では、Wrapperプロセスと制御されたJVMプロセスを対象にすることができます。 それぞれにはプロセッサアフィニティを設定するための独自のプロパティーはありますが、Wrapperのプロパティのみを指定すると、デフォルトで制御されたJVMプロセスは同じ設定を継承し、自動的にWrapperプロセスと同じCPUで実行されます。

技術概要

Wrapperの為のCPUアフィニティの設定方法

対応バージョン :3.5.27
対応エディション :プロフェッショナル版スタンダード版 (未対応)コミュニティー版 (未対応)
対応プラットフォーム :WindowsMac OSX (未対応)LinuxIBM AIX (未対応)FreeBSD (未対応)HP-UX (未対応)Solaris (未対応)IBM z/OS (未対応)IBM z/Linux

Wrapperプロセスの為にプロセッサアフィニティに仕様されるプロパティは下記に解説します:

たとえば、Wrapperを1号と2号のCPUのみで実行させたい場合は、構成ファイルに次のプロパティセットを書き込むことができます。

wrapper.cpu_affinity.set=TRUE
wrapper.cpu_affinity.default=FALSE
wrapper.cpu_affinity.1=TRUE
wrapper.cpu_affinity.2=TRUE

逆に、Wrapperを1号と2号以外のすべてのCPUで実行させたい場合は、次のように書き込むことができます:

wrapper.cpu_affinity.set=TRUE
wrapper.cpu_affinity.default=TRUE
wrapper.cpu_affinity.1=FALSE
wrapper.cpu_affinity.2=FALSE

JVMプロセスの為のCPUアフィニティの設定方法

対応バージョン :3.5.27
対応エディション :プロフェッショナル版スタンダード版 (未対応)コミュニティー版 (未対応)
対応プラットフォーム :WindowsMac OSX (未対応)LinuxIBM AIX (未対応)FreeBSD (未対応)HP-UX (未対応)Solaris (未対応)IBM z/OS (未対応)IBM z/Linux

Javaアプリケーションとすべてのチャイルドプロセスやスレッドが自動的に同じ構成を継承し、同じCPU上で実行されるため、以前の例では、ほとんどの場合十分なはずです。 しかし、Wrapperとその制御されたプロセスに対し、異なるCPUアフィニティ設定を指定したい場合は、次のプロパティセットを使用することで可能になります。

上記紹介したプロパティと同様にご使用できます。

例1(JVMを1号と2号のCPUのみで実行させます)
wrapper.cpu_affinity.set=TRUE
wrapper.java.cpu_affinity.default=FALSE
wrapper.java.cpu_affinity.1=TRUE
wrapper.java.cpu_affinity.2=TRUE
例2(1号と2号以外のすべてのCPUでJVMを実行できるようにします)
wrapper.cpu_affinity.set=TRUE
wrapper.java.cpu_affinity.default=TRUE
wrapper.java.cpu_affinity.1=FALSE
wrapper.java.cpu_affinity.2=FALSE

CPUアフィニティが機能しているか確認方法

前の例では、最初のCPUはインデックス1で指定され、二つ目のCPUはインデックス2等々に指定されているのが確認できます。 ご利用のシステムのCPU使用率をチェックすると、最初のCPUにインデックス0が割り当てられ、インデックス1には別のCPUが割り当てられることがあります。 Wrapperで設定する際、最初のCPUはいつもインデックス1が割り当てられます。

WindowsでCPU使用率を確認するにはタスクマネージャーを開き、パフォーマンスタブを選択し、メインパネルで右クリックをするとメニューが表示されますのでグラフの変更理論プロセッサをクリックしてください。 アプリケーションを1号と2号のCPUのみで実行するように設定した場合は、次のように表示されます。


CPUの使用率(タスクマネージャー)

LinuxでCPUの使用率を確認するには、ターミナルのトップコマンドを押すと理論プロセッサの詳細が表示されます。

UbuntuのシステムモニターGUIウィンドウを開くとCPU使用率の確認:


UbuntuでのCPU使用率 (システムモニター)