Javaのエグゼキュータを正しく使用する方法を理解しようとしています。にタスクを送信することにExecutorService
は、独自のオーバーヘッドがあることに気付きました。しかし、それがそれと同じくらい高いのを見て私は驚いています。
私のプログラムは、可能な限り低いレイテンシで大量のデータ(株式市場データ)を処理する必要があります。ほとんどの計算は、かなり単純な算術演算です。
私は非常に単純なものをテストしようとしました: " Math.random() * Math.random()
"
最も単純なテストでは、この計算を単純なループで実行します。2番目のテストは、匿名のRunnable内で同じ計算を実行します(これは、新しいオブジェクトを作成するコストを測定することになっています)。3番目のテストはに合格Runnable
しますExecutorService
(これは、エグゼキュータを導入するコストを測定します)。
私は私のちっぽけなラップトップ(2 cpus、1.5ギグラムRAM)でテストを実行しました:
(in milliseconds)
simpleCompuation:47
computationWithObjCreation:62
computationWithObjCreationAndExecutors:422
(4回の実行のうち約1回、最初の2つの数値は等しくなります)
エグゼキュータは、単一のスレッドで実行するよりもはるかに長い時間がかかることに注意してください。スレッドプールのサイズが1〜8の場合、数値はほぼ同じでした。
質問:私は明らかな何かを見逃していますか、それともこれらの結果は期待されていますか?これらの結果は、エグゼキュータに渡すタスクはすべて、重要な計算を実行する必要があることを示しています。何百万ものメッセージを処理していて、各メッセージに対して非常に単純な(そして安価な)変換を実行する必要がある場合でも、エグゼキュータを使用できない可能性があります...複数のCPUに計算を分散しようとすると、単にコストがかかる可能性があります単一のスレッドでそれらを実行します。設計上の決定は、私が当初考えていたよりもはるかに複雑になります。何かご意見は?
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ExecServicePerformance {
private static int count = 100000;
public static void main(String[] args) throws InterruptedException {
//warmup
simpleCompuation();
computationWithObjCreation();
computationWithObjCreationAndExecutors();
long start = System.currentTimeMillis();
simpleCompuation();
long stop = System.currentTimeMillis();
System.out.println("simpleCompuation:"+(stop-start));
start = System.currentTimeMillis();
computationWithObjCreation();
stop = System.currentTimeMillis();
System.out.println("computationWithObjCreation:"+(stop-start));
start = System.currentTimeMillis();
computationWithObjCreationAndExecutors();
stop = System.currentTimeMillis();
System.out.println("computationWithObjCreationAndExecutors:"+(stop-start));
}
private static void computationWithObjCreation() {
for(int i=0;i<count;i++){
new Runnable(){
@Override
public void run() {
double x = Math.random()*Math.random();
}
}.run();
}
}
private static void simpleCompuation() {
for(int i=0;i<count;i++){
double x = Math.random()*Math.random();
}
}
private static void computationWithObjCreationAndExecutors()
throws InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(1);
for(int i=0;i<count;i++){
es.submit(new Runnable() {
@Override
public void run() {
double x = Math.random()*Math.random();
}
});
}
es.shutdown();
es.awaitTermination(10, TimeUnit.SECONDS);
}
}