0

最初的问题:

我有一个使用 ExecutorService 来运行 4 个固定线程池的应用程序。当我使用这种架构时,应用程序在 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 指出它。

4

1 回答 1

1

我能想到的唯一一件事是两个系统上的内存设置有所不同,并且您在 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

Another thing to consider is that if your Perform tasks are very small then you may be just testing the context switching of the OS more than anything else. But I wouldn't think it would slow down over time on its own.

于 2012-02-14T17:58:54.487 回答