Der beigefügte einfache Java-Code sollte alle verfügbaren CPU-Kerne laden, wenn er mit den richtigen Parametern gestartet wird. So zum Beispiel, starten Sie es mitWarum verwendet dieser Java-Code nicht alle CPU-Kerne?
java VMTest 8 int 0
und es wird 8 Threads beginnen, die nichts anderes tun, als Looping und das Hinzufügen von 2 auf eine ganze Zahl. Etwas, das in Registern läuft und nicht einmal neuen Speicher zuweist.
Das Problem, das wir jetzt haben, ist, dass wir keine 24-Kern-Maschine (AMD 2 Sockel mit je 12 Kernen) bekommen, wenn wir dieses einfache Programm (mit 24 Threads natürlich) laufen lassen. Ähnliches passiert mit 2 Programmen zu je 12 Threads oder kleineren Maschinen.
Also unser Verdacht ist, dass die JVM (Sun JDK 6u20 auf Linux x64) nicht gut skaliert.
Hat jemand ähnliche Dinge gesehen oder hat die Fähigkeit, es auszuführen und zu melden, ob es auf seinem Rechner gut läuft (> = nur 8 Kerne)? Ideen?
Ich habe das auf Amazon EC2 mit 8 Kernen auch versucht, aber die virtuelle Maschine scheint anders als eine echte Box zu laufen, so dass das Laden völlig seltsam verhält.
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);
}
}
Zusätzliche Informationen. Habe gerade herausgefunden, dass die 64bit-Version des JDK die Kerne wesentlich besser lädt (ca. 90%) als die 32bit-Version (ca. 45%). Das ist seltsam, weil das Betriebssystem und die AMD-CPU 32bit unterstützen und ich während dieses Tests keine Speicheroperationen ausführe. – ReneS
Nur zum Verständnis - warum verwenden Sie nicht die Methode invokeAll (..)? Und warum benutzt du keine callables, soweit ich weiß, runnable ist nicht Teil von java.concurrent? – InsertNickHere
Sie sollten auch nach anderen laufenden Prozessen Ausschau halten. Haben Sie einen "sauberen" Lauf gemacht, ohne dass andere Programme/Prozesse CPU-Zeit benötigen? – InsertNickHere