Java:Executor服务在linux上运行速度较慢,而在Windows上则不然



初始问题:

我有一个应用程序,它使用ExecutorService来运行4个固定线程池。当我使用这种体系结构时,应用程序在Windows上运行得更快,而不是单线程体系结构。但是,当我在linux中运行ExecutorService体系结构时,我的应用程序的性能比单线程应用程序差。

两台机器上的CPU和其他硬件是相同的。我甚至试过不同的机器,结果都是一样的。我甚至试图将修复后的ThreadPool限制为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 Open JDK1.6.0_20

编辑:

我试着在linux上添加Xincgc,在最初的几分钟里,代码运行得像预期的那样快,然后它开始快速变慢。请注意,我创建的代码块在我的应用程序中运行了无数次,这是否表明JVM GC在不同的操作系统中表现不同?

试验后:

在尝试了4台不同的linux机器之后,看起来openJDK引起了问题。我一开始不应该安装openJDK,但感谢@Alfabravo指出了这一点。

我唯一能想到的是,在这两个系统上,at的内存设置在某种程度上不同,而且在Linux早期,内存不足。以下是一些尝试:

  • 增加Linux下的内存设置(duh)。-Xmx1G什么的
  • 在收获后将每个未来分配给null。这可能没有什么影响,但对GC来说可能是值得的。

    for(int i = 0; i < n; i++) {
       future[i].get();
       future[i] = null;
    }
    
  • 不要将Perform对象存储在数组中。提交它们,然后忘记它们。如果您仍然需要它们,则在Future<Perform>中返回它们,然后在使用完它们后将它们设置为null
  • 最好的胜利可能是不要一次提交所有的工作,而是保持100份优秀的工作或其他什么。将Future数组转换为一个列表,获得isDone()isCancelled()的一次,并且只有在列表的大小低于某个阈值时才提交给池。你需要睡一觉才能不旋转。我最近确实这样做了,所以这里有一些示例代码:http://pastebin.com/3TkkxGYT

另一件需要考虑的事情是,如果你的Perform任务很小,那么你可能只是在测试操作系统的上下文切换,而不是其他任何事情。但我不认为它会随着时间的推移而放缓。

相关内容

最新更新