Tuning Linux CPU Performance

A recent kernel change broke my CPU performance tuning. I have an AMD processor which presents 4 cores to the kernel. The process in this article should work for Intel processors although the governors and CPU settings tree may be different. Different kernels may also have different settings. The current kernel allows setting the governor per CPU, but for an earlier kernel the setting was global.

My system is mostly idle, and I want it to be as quiet as possible. However, from time to time it is busy and I want processing to be as fast as possible. I use a small block of shell code to select a governor and ignore niced programs (such as boinc) in selecting processor speed.

The required settings are available in the sysfs file system, which is often mounted as /sys or /sysfs. The path is /sys/devices/system/cpu or /sys/devices/system/cpu. Current settings found by reading the various files in this tree. Writing to the files changes the settings. Files may appear and disappear depending on the current settings. This is why the governor is tuned after it has been applied to the CPUs.

I determined the available governors by reading the file scaling_available_governors file for one of my CPUs. The default setting I get is performance which runs the CPU at its maximum speed and power consumption. The powersave setting does the opposite and runs the CPU at minimum speed and power consumption. My preferred choices are conservative and ondemand which dynamically tune the speed and power consumption based on system load. Both have the option to ignore niced processes when calculating load.

This code segment does the performance tuning. By default it will show the old values before updating them. The VERBOSE setting follows the semantics used for init.d scripts on Ubuntu.

# Change CPU performance governor
# and ignore nice load preference

# Choose governor from available governors listed in
#    /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
# conservative ondemand userspace powersave performance

CPU_PATH=/sys/devices/system/cpu
GOVERNOR=conservative
IGNORE_NICE_LOAD=1

# Set the governor on each CPU
for CPU in ${CPU_PATH}/cpu[0-9]*; do
    [ "$VERBOSE" != no ] && echo ${CPU} $(cat ${CPU}/cpufreq/scaling_governor)
    echo ${GOVERNOR} > ${CPU}/cpufreq/scaling_governor
done

# Set ignore_nice_load for the selected governor (must be active)
NICE_LOAD=$(cat ${CPU_PATH}/cpufreq/${GOVERNOR}/ignore_nice_load)
[ "$VERBOSE" != no ] && echo ignore_nice_load ${NICE_LOAD}
echo ${IGNORE_NICE_LOAD} > ${CPU_PATH}/cpufreq/${GOVERNOR}/ignore_nice_load

I included this in the /etc/rc.local script. Alternatively, it could be configured as a standalone init.d script. On Ubuntu or Debian (and other distributions following the same standards), you can make sure that the /etc/rc.local script will be invoked with the commands:

sudo update-rc.d -f rc.local remove
sudo update-rc.d rc.local defaults