Normally it is left up to the operating system to decide which CPUs or cores of the machine will be used to run an application. Depending on the number of threads required by the application at any given time and the needs of other applications, the OS will try to move threads around as needed to keep the overall load on each CPU balanced. When there are more threads than CPUs (which is the norm), the OS will share CPUs amongst several threads, meaning that threads will be paused until it is their turn. For some applications, this method may not work well, and it can be useful to dedicate certain CPUs or groups of CPUs to specific applications. Most OS platforms provide the ability to specify that a process should only execute on specific CPUs. This is commonly called CPU affinity or CPU pinning.

Dedicating specific CPUs to your application can be a way to ensure that it will always have enough CPU resources. On the contrary, you could explicitly keep some processors unused in order to guarantee sufficient resources for other processes running on the same machine. Setting processor affinity can also significantly optimize CPU cache. In other words, whenever a process changes the CPU, its data is transferred from one CPU to another. This transfer is costly but you can minimize it by pinning the process to a limited number of CPUs. You should, however, be careful to allow enough processors for your application, as it may have the ability to execute parallel tasks on different CPUs when available.

Unfortunately, Java does not provide a solution to launch the JVM with core or processor affinity. Should you want to pin your Java application to specific CPUs, you would have to either use commands like procaff, taskset or invoke native code. Processor affinity These solutions are platform specific.

Solution

The Java Service Wrapper Professional Edition addresses this issue by providing a unified and easy way to configure CPU affinity without having to write code. As of version 3.5.27, only Windows and Linux are supported, but additional platform support will be coming in near future releases.

The configuration can target the Wrapper process as well as its controlled JVM process. Each have their own properties to configure processor affinity but if you only specify those of the Wrapper, by default the controlled JVM process will inherit the same configuration and automatically execute using the same CPU(s) as the Wrapper process.

Technical Overview

How to configure CPU affinity for the Wrapper

Compatibility :3.5.27
Editions :Professional EditionStandard Edition (Not Supported)Community Edition (Not Supported)
Platforms :WindowsMac OSX (Not Supported)LinuxIBM AIX (Not Supported)FreeBSD (Not Supported)HP-UX (Not Supported)Solaris (Not Supported)IBM z/Linux

The properties used to configure the processor affinity for the Wrapper process are described below:

For example, if you want the Wrapper to run only on CPU number 1 and 2, you can write the following set of properties in your configuration file (wrapper.conf):

Example
wrapper.cpu_affinity.set=TRUE
wrapper.cpu_affinity.default=FALSE
wrapper.cpu_affinity.1=TRUE
wrapper.cpu_affinity.2=TRUE

On the contrary, if you want the Wrapper to run on all CPUs except number 1 and 2, you may write the following:

Example
wrapper.cpu_affinity.set=TRUE
wrapper.cpu_affinity.default=TRUE
wrapper.cpu_affinity.1=FALSE
wrapper.cpu_affinity.2=FALSE

How to configure CPU affinity for the JVM process

Compatibility :3.5.27
Editions :Professional EditionStandard Edition (Not Supported)Community Edition (Not Supported)
Platforms :WindowsMac OSX (Not Supported)LinuxIBM AIX (Not Supported)FreeBSD (Not Supported)HP-UX (Not Supported)Solaris (Not Supported)IBM z/Linux

The previous examples should be sufficient in most cases, as your Java application and all its child processes and threads will automatically inherit the same configuration and run on the same CPUs. If you, however, want to specifiy different CPU affinity configurations for the Wrapper and its controlled process, this is possible by using the following set of properties.

You can use these properties the same way as previously shown.

Example 1 (allow the JVM to run only on CPUs number 1 and 2)
wrapper.cpu_affinity.set=TRUE
wrapper.java.cpu_affinity.default=FALSE
wrapper.java.cpu_affinity.1=TRUE
wrapper.java.cpu_affinity.2=TRUE
Example 2 (allow the JVM to run on any CPUs except number 1 and 2)
wrapper.cpu_affinity.set=TRUE
wrapper.java.cpu_affinity.default=TRUE
wrapper.java.cpu_affinity.1=FALSE
wrapper.java.cpu_affinity.2=FALSE

Verify that CPU affinity is working

In the previous example you may have noticed that the first CPU was designated with index 1, the second CPU with index 2 and so forth. If you check CPU usage on your system, the first CPU may sometimes be assigned with index 0 and other times with index 1. When configuring the Wrapper, the first CPU will always be designated with index 1.

To view CPU usage on Windows open the Task Manager, select the tab Performance, then right click on the main panel and in the contextual menu select Change Graph to Logical processors. If you configured your application to run only on CPU number 1 and 2, it should be similar to this:


CPUs usage on Windows (Task Manager)

To view CPU usage on Linux, you can use the top command in your terminal and press 1 to see the details of logical processors.

On Ubuntu you can open System Monitor if you prefer to see CPU usage in a GUI window:


CPUs usage on Ubuntu (System Monitor)