【问题标题】:Multi-core CPU utilization by Java applicationJava 应用程序的多核 CPU 利用率
【发布时间】:2011-10-12 01:02:16
【问题描述】:

我有一个程序,它通过将大文件分成块、排序块并将它们合并到最终排序的文件中来对大文件进行排序。应用程序运行一个线程来从文件加载/保存数据 - 只有一个线程执行 I/O 操作。还有另外两个线程接收块数据,对其进行排序,然后将排序后的数据发送回执行 I/O 的线程。

所以通常有 4 个线程在运行 - 主线程、加载/保存数据的线程和两个排序数据的线程。

我认为在执行期间我会看到 1 个不占用任何 CPU 时间的休眠线程(主线程)和 3 个每个使用 1 个 CPU 内核的活动线程。

当我在具有超线程(24 个 CPU)的双 6 核处理器机器上运行此程序时,我看到所有 24 个 CPU 都已加载 100%!

最初我认为排序算法是多线程的,但在查看 java 源代码后我发现它不是。

我正在使用简单的 Collections.sort(LinkedList) 对数据进行排序...

这里有一些细节:

# java -版本 java版本“1.6.0_26” Java(TM) SE 运行时环境 (build 1.6.0_26-b03) Java HotSpot(TM) 64 位服务器 VM(内部版本 20.1-b02,混合模式) # unname -a Linux 2.6.32-28-server #55-Ubuntu SMP Mon Jan 10 23:57:16 UTC 2011 x86_64 GNU/Linux

我使用 nmon 监控处理器负载。

我将不胜感激对此案例的任何解释以及有关如何控制 CPU 负载的任何建议,因为我这个特定任务不会为其他应用程序留出 CPU 时间

[更新] 我使用 jvisualvm 来计算线程数——它只显示我知道的线程。我还做了一个简单的测试程序(见下文),它只运行一个主线程并得到完全相同的结果——所有 24 个处理器在代码执行期间几乎 100% 忙

public class Test {

    public void run(){
        Random r = new Random();
        int len = r.nextInt(10) + 5000000;
        LinkedList<String> list = new LinkedList<String>();
        for (int i=0; i<len; i++){
                list.add(new String("test" + r.nextInt(50000000)));
        }
        System.out.println("Inserted " + list.size() + " items");
        list.clear();
    }

    public static void main(String[] argv){
        Test t = new Test();
        t.run();
        System.out.println("Done");
    }
}

[更新]
这是我在运行上面的程序时制作的屏幕截图(使用 nmon): http://imageshack.us/photo/my-images/716/cpuload.png/

【问题讨论】:

  • 我们可能需要查看您的代码才能弄清楚这一点。我的猜测是你使用的线程比你想象的要多。
  • 我使用 jvisualvm 来计算线程数——它只显示我知道的线程。我还做了一个简单的测试程序,它只运行一个主线程并得到完全相同的结果。请查看我有问题的更新。
  • 4 线程不能使用 6 核的 100% 利用率。要么你有更多线程,要么你的测量结果有误。
  • 您使用什么程序来监控 CPU 使用率?它可能向您展示了在后台运行的其他一些程序。要么是这样,要么你的测试太短了,它只向你展示了一些与 JVM 启动相关的东西。
  • 我使用 nmon 来监控 CPU 利用率,这里是屏幕截图:link 另外,虽然我没有运行 java 程序 - 它没有显示任何活动。无论如何,我在运行我原来的排序程序时看到的完全一样。老实说,我所期待的正是每个人所期望的——一个线程使用一个 CPU。但看起来 java 使用未链接到底层操作系统线程的绿色线程。据我了解,java 使用自己的线程调度。因此,它可能会导致多个本机线程服务于一个 java 线程???

标签: java multithreading multicore utilization


【解决方案1】:

我建议,这是一个 nmon 而不是 java 问题,为了解决它,我会看一下 top 命令,它提供有关每个进程的 cpu 使用情况的信息。我预测以下结果:您将看到一个 java 线程使用接近 100% 的 cpu 时间(这没关系,因为顶部的每个进程百分比相对于一个(虚拟)核心),可能是第二个和第三个 java 线程有很多更少的 cpu 使用(I/O 线程)。根据 gc 的选择,您甚至可能会发现一个或多个 gc-Threads,但远少于 20 个。

但是,HotSpot 不会(据我所知甚至不能)自行并行化顺序任务。

【讨论】:

  • 我用“top -H”检查了应用程序,java拥有很多线程。然后我在执行期间使用“jstack”检查了应用程序,发现有很多 gc 线程:“GC task thread#0”....“GC task thread#14”所以,我相信生成了 nmon 显示的加载通过 GC 线程。我将阅读有关如何控制 GC 的更多信息。 @Jonathan 感谢您再次提出 GC 的想法,您已经获得了我的投票
  • 我使用 -XX:ParallelGCThreads 来控制线程数并在 nmon 中得到完全预期的结果 - 4 个应用程序线程使用 4 个内核。 @Johnatan 再次感谢!
猜你喜欢
  • 1970-01-01
  • 2021-03-02
  • 1970-01-01
  • 2013-03-26
  • 2011-08-19
  • 2012-03-19
  • 2011-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多