初步问题:
我有一个使用ExecutorService运行4个fixedThreadPool的应用程序。当我使用这种架构时,应用程序在Windows上以单线程架构运行得更快。但是当我在linux中运行ExecutorService架构时,我的应用程序的性能比单独的线程应用程序更糟糕。
两台机器上的CPU和其他硬件完全相同。我甚至尝试过不同的机器并获得相同的结果。我甚至试图将fixedThreadPool限制为3或2,但性能仍然较慢。什么可能是我错过的变量导致Linux机器的缓慢?
ExecutorService execSvc =
Executors.newFixedThreadPool(NUMBER_OF_PROCESSORS);
Perform perform[] = new Perform[n];
Future<?>[] future = new Future<?>[n];
for(int i=0;i<n;i++)
future = execSvc.submit(perform[i]);
for(int i=0;i<n;i++)
//To wait until all done
future[i].get();
两个操作系统都在同一台机器上运行。 JAVA版本:windows 1.6.0_22,linux打开JDK1.6.0_20
编辑:
我尝试在linux上添加-Xincgc,似乎在最初的几分钟内代码运行速度如预期的那样,之后它开始加速并迅速减速。请注意我创建的代码块在我的应用程序中运行了数十亿次,这是否表明JVM GC在不同的操作系统中表现不同?
试用后:
尝试使用4台不同的Linux机器后,看起来openJDK导致了问题。我不应该首先安装openJDK,但感谢@Alfabravo指出它。
答案 0 :(得分:1)
关于我唯一能想到的是内存设置在两个系统上有所不同,而且你早先在Linux-land中耗尽了内存。这里有一些尝试:
-Xmx1G
或其他收获后将每个未来分配到null
。这可能影响不大,但可能值得帮助GC。
for(int i = 0; i < n; i++) {
future[i].get();
future[i] = null;
}
Perform
个对象存储在数组中。只需提交它们就可以忘掉它们。如果你仍然需要它们,那么在Future<Perform>
中返回它们,然后在完成它们时将它们设置为null。Future
数组转换为列表并获取isDone()
或isCancelled()
的onces,并且只有在列表大小低于某个阈值时才提交到池中。你需要睡觉才能旋转。我最近这样做了,所以这里有一些示例代码:http://pastebin.com/3TkkxGYT 另一件需要考虑的事情是,如果你的Perform
任务非常小,那么你可能只是测试操作系统的上下文切换而不是其他任何事情。但我不认为它会随着时间的推移而减速。