我正在尝试弄清如何正确使用Java的Executors。我意识到向ExecutorService提交任务会有一定的开销。但是,我惊讶地发现它的开销是如此之高。
我的程序需要处理大量的数据(股市数据),并且需要尽可能低的延迟。大部分计算都是相当简单的算术运算。
我尝试测试了一个非常简单的东西:“Math.random() * Math.random()
”
最简单的测试在一个简单的循环中运行这个计算。第二个测试将相同的计算放在匿名Runnable内(这应该测量创建新对象的成本)。第三个测试将Runnable传递给一个ExecutorService(这将测量引入执行器的成本)。
我在我的小笔记本电脑上运行了这些测试(2个CPU,1.5 GB RAM):
(in milliseconds)
simpleCompuation:47
computationWithObjCreation:62
computationWithObjCreationAndExecutors:422
注意,执行器比在单个线程上执行要花费更多的时间。在线程池大小为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);
}
}