Java (JVM) Processor Affinity - A Quick Hack

With muti-processor/muticore systems now ubuitious it is unfortunate that Java does not provide JVM launch with core or processor affinity.

Most operating system now have commands to support this feature:

This article shows how to use these commands with a java wrapper to provide java jvm processor affinity.

Procaff on Windows

On Windows we use the following command to launch the Jvm bound to a specific processor:

  #Starting jvm on CPU 1 synchronously 
  procaff /wait 2 java -server ...

Taskset - on Unix, Linux

On Unix

   # set the process 13545 to processor 1
   taskset -c 1 -p 13545

Launching the Command from Java

For automatic builds of performances runs we would like to be able to execute our processor affinity commands from Java. The following Java class will exec our native command. We can also check that existing processors don't already exist.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
 
public class StartOnProcessor {
 
  public static List<String> listRunningProcesses() {
	List<String> processes = new ArrayList<String>();
	try {
		String line;
		Process p = Runtime.getRuntime().exec("tasklist.exe /fo csv /nh");
		BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
		while ((line = input.readLine()) != null) {
			if (!line.trim().equals("")) {
				// keep only the process name
				line = line.substring(1);
				processes.add(line.substring(0, line.indexOf("\"")));
				System.out.println(line.substring(0, line.indexOf("\"")));
			}
 
		}
			input.close();
	} catch (Exception err) {
		err.printStackTrace();
	}
	return processes;
}
 
/**
 * @param args
 */
public static void main(String[] args) {
	List processes = listRunningProcesses();
	if (processes.contains("procaff.exe")) {
		System.out.println("procaff.exe affinity process is already running ");
		System.exit(0);
	}
	String cmd = "procaff.exe";
	try {
		Runtime rt = Runtime.getRuntime();
		System.out.println("Execing " + cmd);
		Process proc = rt.exec(cmd);
		// any error message?
		StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");
 
		// any output?
		StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");
 
		// kick them off
		errorGobbler.start();
		outputGobbler.start();
 
		int exitVal = proc.waitFor();
		System.out.println("ExitValue: " + exitVal);
		System.out.println("Server should be up and running ..");
	} catch (Exception e) {
		System.out.println("Exception occured");
		e.printStackTrace();
	}
}
}

and the utility StreamGobbler Utility Class