【发布时间】:2011-02-21 11:25:26
【问题描述】:
当使用正确的参数启动它时,附加的简单 Java 代码应该会加载所有可用的 cpu 内核。因此,例如,您以
开头java VMTest 8 int 0
它将启动 8 个线程,这些线程除了循环并将 2 加到一个整数之外什么都不做。在寄存器中运行甚至不分配新内存的东西。
我们现在面临的问题是,在运行这个简单的程序(当然是 24 线程)时,我们没有加载 24 核机器(AMD 2 个插槽,每个插槽有 12 个内核)。类似的事情发生在 2 个程序每个 12 个线程或更小的机器上。
所以我们怀疑 JVM(Linux x64 上的 Sun JDK 6u20)不能很好地扩展。
有没有人看到类似的东西或有能力运行它并报告它是否在他/她的机器上运行良好(请>= 8 核)?想法?
我也在 8 核的 Amazon EC2 上尝试过,但虚拟机的运行似乎与真实机器不同,因此加载行为非常奇怪。
package com.test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class VMTest
{
public class IntTask implements Runnable
{
@Override
public void run()
{
int i = 0;
while (true)
{
i = i + 2;
}
}
}
public class StringTask implements Runnable
{
@Override
public void run()
{
int i = 0;
String s;
while (true)
{
i++;
s = "s" + Integer.valueOf(i);
}
}
}
public class ArrayTask implements Runnable
{
private final int size;
public ArrayTask(int size)
{
this.size = size;
}
@Override
public void run()
{
int i = 0;
String[] s;
while (true)
{
i++;
s = new String[size];
}
}
}
public void doIt(String[] args) throws InterruptedException
{
final String command = args[1].trim();
ExecutorService executor = Executors.newFixedThreadPool(Integer.valueOf(args[0]));
for (int i = 0; i < Integer.valueOf(args[0]); i++)
{
Runnable runnable = null;
if (command.equalsIgnoreCase("int"))
{
runnable = new IntTask();
}
else if (command.equalsIgnoreCase("string"))
{
runnable = new StringTask();
}
Future<?> submit = executor.submit(runnable);
}
executor.awaitTermination(1, TimeUnit.HOURS);
}
public static void main(String[] args) throws InterruptedException
{
if (args.length < 3)
{
System.err.println("Usage: VMTest threadCount taskDef size");
System.err.println("threadCount: Number 1..n");
System.err.println("taskDef: int string array");
System.err.println("size: size of memory allocation for array, ");
System.exit(-1);
}
new VMTest().doIt(args);
}
}
【问题讨论】:
-
附加信息。刚刚发现 JDK 的 64 位版本加载内核的方式(大约 90%)比 32 位版本(大约 45%)更好。这很奇怪,因为操作系统和 AMD cpu 支持 32 位,而我在测试期间没有运行任何内存操作。
-
只是为了理解-为什么不使用 invokeAll(..) 方法?而且你为什么不使用可调用对象,据我所知,runnable 不是 java.concurrent 的一部分?
-
您还应该注意其他正在运行的进程。您是否进行了“干净”运行,没有其他程序/进程占用 CPU 时间?
-
“int”任务的本机版本加载内核的能力如何? “字符串”/“int”有什么区别?发布一些汇总数字?
-
@InsertNickHere:只是想快速编写代码以使用 Java 加载 cpus。只是为了证明一个理论。是的,这是一次干净利落的运行。 @Justin:我没有本机版本。它是关于检查Java是否可以在理论上处理核心和最简单的代码。
标签: java scalability cpu multicore scaling