Multithreaded CPU load on Windows

Hi,

I'm trying to determine whether my Pentium D running 32bit Windows XP is load-balancing between the two CPU cores correctly. To do this I'm running the following small test app. (It's a complete app and should compile for anyone)

import java.text.DecimalFormat;

import java.util.Random;

/**

* I am interested in finding out if the Windows implementation of the Sun

* JVM will multithread on a dual processor. I have a Pentium D at home and

* I'm not always convinced that it load-balances very well. Let's see if

* it offers an advantage when using Java to write a multithreaded program.

*

* @author Gordon

* @version 20070421 Initial Creation

*/

publicclass MultiThread{

publicstaticfinalint NUM_THREADS = 1000;

publicstaticfinal DecimalFormat FORMATTER =new DecimalFormat("0000");

public MultiThread(){

super();

}

/**

* @param args

*/

publicstaticvoid main(String[] args){

for(int i = 0; i < NUM_THREADS; i++){

Thread t =new Thread(new Thrash(),"Thread" + FORMATTER.format(i));

t.setPriority(Thread.MAX_PRIORITY);

t.start();

synchronized(System.out){

try{

System.out.wait(10);

}

catch(InterruptedException ex){

System.out.notifyAll();

}

}

}

}

/**

* Define a Runnable that does something fairly heavy, but that will complete of

* its own accord eventually.

*/

publicstaticclass Thrashimplements Runnable{

private Random _rand =null;

public Thrash(){

_rand =new Random(System.currentTimeMillis());

}

publicvoid run(){

int i = 0;

while(i < 1000){

int r = _rand.nextInt(10);

i += r;

synchronized (System.out){

System.out.println(Thread.currentThread().getName() +" i = " + i);

r *= r;

try{

// give other threads a chance to get going

System.out.wait(25);

}

catch(InterruptedException ex){

System.out.notifyAll();

}

}

}

}

}

}

The code is compiled with JDK1.5.0_11.

Running from a command prompt seems to load both processors fairly evenly if I allow standard out to stream to the console. But if I pipe output to a text file then only CPU 1 seems to have any load. I suspect this is the truer image of what's going on and the even load in the first case is as much Windows struggling to keep up with the output.

Is the Windows implementation of the 1.5 JVM multithreaded across dual core CPUs? Should I expect to see an evenly spread load for my example program? Have I misunderstood something and my program is wrong. (A race condition I'm missing? Not a heavy enough load to force it onto the second procesosr?)

Thanks in advance...

Gordon

[5175 byte] By [ch0rlt0na] at [2007-11-27 1:55:00]
# 1

Your test code isn't written to be run concurrent. i.e. One thread runs most of the time while all the other threads spend their time blocked by the synchronized code. Since only one thread run's at a time, there isn't much of need to switch cpu's.

Here is some code that I posted before that Spins each of your CPU and occasionally outputs to System.out. The % operator prevents it from doing System.out each time through the loop.

public class Spin implements Runnable {

public static void main(String[] args) {

int threads = Runtime.getRuntime().availableProcessors();

if (args.length > 0) {

threads = Integer.parseInt(args[0]);

}

for (int i=0; i<threads; i++) {

new Thread(new Spin(),"Spin " + i).start();

}

}

public void run() {

for(long i=0; i != 10000000000; i++) {

if (i % 10000000 == 0) {

System.out.println("Thread \"" + Thread.currentThread().getName() + "\" is on iteration " + i);

}

}

}

}

>

Caffeine0001a at 2007-7-12 1:27:26 > top of Java-index,Core,Core APIs...
# 2

Thanks for the explanation and clear code example. I see what I was doing wrong.

For anyone interested, my suspcion that my computer wasn't load-balancing correctly was right. I didn't know about Runtime.availableProcessors, so the big surprise was that it was returning a value of 1. A big trawl of the net finally led me to an explanation of processor affinity and the discovery that explorer.exe was only set to run on CPU0, and not both CPU0 and CPU1 as it should be. (Since I didn't know the Windows Task Manager could set this I can't imagine it was me that did this). All child processes then also only had an affinity for CPU0. Setting explorer.exe to have an affinity for both processors, opening a new DOS prompt and re-running the JVM correctly loaded both processors.

Certain processes, Firefox for example, had the correct affinity and must determine this for themselves which is why the second processor did occasionally seem to have some load.

Thanks again Caffeine.

ch0rlt0na at 2007-7-12 1:27:26 > top of Java-index,Core,Core APIs...