Save Energy with GNU/Linux

Motivation

I think that ever since I got my first laptop, it has been quite a quest to discover the best ratio between performance and powersave options using GNU/Linux. In fact, I presume many people spend a lot of time (and a lot means several months and even years) discovering which are the most interesting options in the Linux kernel and how to use different power saving systems, such as APM or ACPI, for properly configuring a system (typically a laptop).

The point is that using the proper configuration, we can get the maximum of our computer when referring to power saving, but also keeping a good performance ratio that may not be very affected by the powersave settings. This article, therefore, intends to visit the most common options in nowadays Linux kernels and the system tools available in GNU/Linux for discovering the most resource-consuming devices and improving both the power saving and performance on our computer.

Please note that this article, as many on this website, has been written based on a Debian GNU/Linux distribution and using a concrete kernel version (2.6.27 in this case). Nevertheless, most of the stuff should be totally available and compatible across GNU/Linux systems using a kernel version 2.6.27 or higher.

Kernel Configuration

The first thing when modifying our GNU/Linux distro is always the same: configuring the kernel. In the Linux kernel, there are many powersave options for different devices and subsystems, and therefore we will visit them in separate subsections along this chapter.

Power Management Options

This is the main menu for powersave settings in the Linux kernel configuration and it is hence the most important kernel configuration menu along this document.

  • [*] Power Management support
  • [*] Suspend to RAM and standby
  • [*] Hibernation (aka 'suspend to disk')
  • [*] ACPI (Advanced Configuration and Power Interface) Support --->
    • [*] Future power /sys interface
    • [*] Deprecated /proc/acpi/event support
    • <*> AC Adapter
    • <*> Battery
    • <*> Button
    • <*> Video
    • <*> Fan
    • <*> Processor
    • <*> Thermal Zone
  • CPU Frequency scaling --->
    • [*] CPU Frequency scaling
    • Default CPUFreq governor (ondemand) --->
    • _*_ 'ondemand' cpufreq policy governor
    • <*> ACPI Processor P-States driver
  • [*] CPU idle PM support

Let's analyze these options one by one. First of all, the whole Power Management support has to be, obviously, enabled in order to have power management support provided by the kernel.

Now, in order to be able to put the laptop or computer to sleep, we need the Suspend to RAM and standby support. With this option, we are able to put to sleep our computer, so that it doesn't consume almost any energy when not being used. Further, the Hibernation support allows us to put the computer to sleep forever. That means that the whole operating system state is saved in the hard disk and then it is restored when starting the computer once again. Therefore, when the computer boots, it will search for an existing restauration on the hard disk and will restore everything, and so we will see the computer as it was left when going into hibernation.

For people using i386 or x86_64 architectures, ACPI should be a must, since it provides the advanced interfacing for monitoring and controlling the machine power resources. ACPI will provide support for registering events (e.g. closing the laptop's lid, plugging the battery, connecting the AC adapter, etcetera), and so we can configure a set of scripts to make the computer react to these events. For instance one may configure the computer to perform certain tasks when the battery is connected (for instance, to change some settings for power saving) or when connecting the AC adapter (for instance, to change to a higher-performance settings).

In order to register such ACPI events, it is necessary to include the Deprecated /proc/acpi7event support option, since the acpid daemon uses this interface.

The CPU Frequency scaling option is almost mandatory, but not always. However, in laptops I would say it is almost a must. This is because, thanks to this driver, the CPU can scale down to lower frequencies when not being used, and hence cool down the temperature of the chipset of our computer. Using the ondemand driver, the CPU will automatically scale up or down according to the current needs of the system, which is the most suitable option so far. Finally, the option CPU idle PM is used to tell the Linux kernel to deactivate the CPU (actually put in in idle mode) when it is not being used (this happens rarely, but it saves some energy in some cases).

I2C Support (SMBus)

I2C is an acronym for Inter-Integrated Circuit and it provides access to certain details of the low-level hardware components on a computer. In the Linux kernel, this means that we may have monitoring access to low-level devices such as certain controllers and so forth. I2C is usually referred to as SMBus.

Typically it is enough to enable the general support, the device interface and the specific hardware bus driver for the motherboard in use. These are the usual options to configure in the Linux kernel:

  • <*> I2C support -->
    • <*> I2C device interface
    • [*] Autoselect pertinent helper modules
    • I2C Hardware Bus support --->
      • <*> Intel 82801 (ICH)

In the configuration sample above, I selected the general options plus the Intel 82801 (ICH) driver, which is suitable for most modern Intel-based computer platforms. However, you should select the specific driver according to your computer platform (typically matching the vendor and model of your motherboard).

Please note that the I2C driver in the Linux kernel serves as a monitoring tool, rather than a controlling interface. Therefore, it is used to provided extended support for reporting detailed information about certain devices, but not for controlling them, at least directly from its interface.

Hardware Monitoring

The Hardware Monitoring menu is somewhat similar, in purpose, to the I2C support, since it provides several drivers for monitoring the state of certain hardware components, such as CPU cores, chipsets, etcetera. For instance, for Intel-based computer platforms, it is interesting to enable the Intel Core (2) Duo/Solo temperature sensor, which will tell us about the temperature of the CPU cores and their cooling states. Besides that, there are many drivers in the list and they should be analyzed carefully (reading the built-in help) in order to discover which sensor might be the most accurate for our specific platform and set of devices.

Other Drivers

Besdies the general power management support menu and the monitoring menus, there might be some extra option included in the Device Drivers menu specific for each piece of hardware.

One good example is the power saving settings for audio cards (ALSA) or even USB devices. In the case of ALSA, Intel sound cards provide a powersave settting named Aggressive power-saving on HD-audio, which forces the sound card to be disabled when not using it after a given timeout. Another example of powersave setting may be found in the USB menu, named USB selective suspend/resume and wakeup, which suspends and resumes the USB devices according to the state of the computer energy profile.

Certainly, you shall research yourself in search of new options that might be, at a first sight, hidden to the user but they are however definitely there in the kernel and may be enabled, giving you more autonomy with your laptop or even being more environmentally friendly using any general-purpose computer.

System Tuning

Once the kernel is set up and well configured providing all the options for accessing the hardware and setting it to its lower-consume state, it is necessary to configure the userland part of the system in order to provide efficient ways of controlling our hardware.

For a quick start, you should have installed the following packages:

~$ sudo apt-get install acpid hdparm powertop

First, the acpid daemon will be always running in background checking for ACPI events to happen. This means that typical energy-based events will be caught and the system will react to them. Let's see an example:

When we are using our laptop on battery power, and we plug the AC adapter, the kernel will notify the userland with an event telling that the AC adapter has been plugged in. This event is published on /prco/acpi/event, which is in turn read by the acpid daemon (running in background), and hence theh ACPI daemon can run some program or change some settings on the computer according to the published event.

Normally, the ACPI scripts are stored in /etc/acpi/actions, and they are triggered by the files contained in /etc/acpi/events. Accordingly, we may set up the event files in /etc/acpi/events and tell the ACPI daemon what to do any time something happens on the system. For instance, I have two different scripts: one for enabling all the performance settings and another one for enabling the powersave settings on the system. When the AC adapter is connected, I tell ACPI to run the script for enabling all the performance settings (since I don't care much about the consume on my laptop). However, when the AC adapter is disconnected, I tell the ACPI daemon to set all the powersave settings enabled, in order to achive the longest battery life possible.

ACPI Scripts

For configuring the ACPI actions, first we have to tell the acpid daemon to check for certain events and so react to them when something happens. The configuration files for making acpid watch events are located at /etc/acpi/events. I have the three following files:


/etc/acpi/events/ac:

event=ac_adapter
action=/etc/acpi/actions/ac.sh "%e"


/etc/acpi/events/lid:

event=button/lid.*
action=/etc/acpi/actions/lid.sh "%e"


/etc/acpi/events/powerbtn:

# /etc/acpi/events/powerbtn
# This is called when the user presses the power button and calls
# /etc/acpi/powerbtn.sh for further processing.

# Optionally you can specify the placeholder %e. It will pass
# through the whole kernel event message to the program you've
# specified.

# We need to react on "button power.*" and "button/power.*" because
# of kernel changes.

event=button[ /]power
action=/etc/acpi/powerbtn.sh

According to the scripts presented above, when one of the three events (AC adapter plug in/out, lid open/close or power button press), the acpid daemon will execute the script given by the parameter action=. Now let's check out the action scripts:


/etc/acpi/action/ac.sh:

#!/bin/sh

# This script is executed by ACPI when the AC adapter is connected or
# disconnected.

# Enable powersave or performance settings
AC=`acpi -aB | grep "on-line"`
if [ "$AC" == "" ]; then
    # If running on battery, enable powersave settings
    exec /usr/local/bin/lowper
else
    # If running on AC, enable performance profile
    exec /usr/local/bin/highper
fi


/etc/acpi/action/lid.sh:

#!/bin/sh

# Easy way to send the laptop to sleep
echo "mem" > /sys/power/state


/etc/acpi/powerbtn.sh:

#!/bin/sh
# /etc/acpi/powerbtn.sh
# Initiates a shutdown when the power putton has been
# pressed.

# Skip if we just in the middle of resuming.
test -f /var/lock/acpisleep && exit 0

# If gnome-power-manager, kpowersave or klaptopdaemon are running, let
# them handle policy This is effectively the same as 'acpi-support's
# '/usr/share/acpi-support/policy-funcs' file.

if pidof gnome-power-manager kpowersave > /dev/null ||
  (pidof dcopserver > /dev/null && test -x /usr/bin/dcop && /usr/bin/dcop kded kded loadedModules | grep -q klaptopdaemon) ; then
    exit
fi

# If XFCE is running, let it handle policy This is effectively the same as
# 'acpi-support's '/usr/share/acpi-support/policy-funcs' file.
if pidof xfce4-session > /dev/null; then
    exit
fi

# Otherwise, if KDE is found, try to ask it to logout.
# If KDE is not found, just shutdown now.
if ps -Af | grep -q '[k]desktop' && pidof dcopserver > /dev/null && test -x /usr/bin/dcop ; then
    KDESES=`pidof dcopserver | wc -w`
    if [ $KDESES -eq 1 ] ; then
        # single KDE session -> ask user
        /usr/bin/dcop --all-sessions --all-users ksmserver ksmserver logout 1 2 0
        exit 0
    else
        # more than one KDE session - just send shutdown signal to all of them
        /usr/bin/dcop --all-sessions --all-users ksmserver ksmserver logout 0 2 0 && exit 0
    fi
fi

# If all else failed, just initiate a plain shutdown.
/sbin/shutdown -h now "Power button pressed"

First things first. The first script was ac.sh. This script will be executed any time the AC adapter is connected or disconnected. Therefore, we must check if, when the event is generated, the AC adapter is connected or not. In case it is, it means that it has been connected right now, and we probably want to enable high-performance settings (e.g. execute your own script, like I do when calling /usr/local/bin/highper). On the other hand, if the AC adapter has been disconnected, it means that we are running on battery, and hence we might want to enable the powersave settings (e.g. when I call to /usr/local/bin/lowper). Before checking these two scripts for high-performance and powersave settings, let's analyze the rest of ACPI.

The second script is lid.sh, which is executed any time the laptop lid is open or closed. However, only when the lid is closed, the actions in this script will be taken in account, since waking up from sleep mode doesn't let acpid to run this script. Thus, the contents of this file are quite simple: we tell the computer to go to sleep. Nonetheless, it is totally possible to perform any kind of action in this script before going into sleep mode. For instance, you may want to play some sound or display an informative message on the graphical interface for any user.

Last, the powerbtn.sh script, which is automatically created by the installation of the acpid package, and that we do not generally need to touch, but can be customized for any specific purpose of course.

Finally, what's the content of the files lowper and highper? These scritps are my own scripts and I separated them from the ACPI scripts so that I can use them from anywhere in my computer. Here are the contents of each file (which are analyzed in the subsequent sections):


/usr/local/bin/lowper:

#!/bin/sh

# lowper -- Set computer to low performance parameters
# v0.2
perfile="/tmp/performance"


# Global settings (spindown is in seconds)
disk="/dev/sda"
spindown="30"
spindown=`expr $spindown / 5`


# Main program
echo -n "Enabling powersave settings: "

# SATA minimum power profile select
echo "min_power" > /sys/class/scsi_host/host0/link_power_management_policy
echo "min_power" > /sys/class/scsi_host/host1/link_power_management_policy
echo "min_power" > /sys/class/scsi_host/host2/link_power_management_policy
echo "min_power" > /sys/class/scsi_host/host3/link_power_management_policy

# Hard disk Advanced Power Management (aggressive saving)
hdparm -S $spindown -B 1 $disk >/dev/null 2>&1

# CD-ROM polling disable
hal-disable-polling --device /dev/cdrom >/dev/null 2>&1

# CPU frequency limit
echo "800000" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq

# Report low performance to the system
echo "low" > $perfile

echo "done."


/usr/local/bin/lowper:

#!/bin/sh

# highper -- Set computer to high performance parameters
# v0.2
perfile="/tmp/performance"


# Global settings (spindown is in seconds)
disk="/dev/sda"
spindown="300"
spindown=`expr $spindown / 5`


# Main program
echo -n "Enabling high-performance settings: "

# CPU frequency limit
echo "2267000" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq

# SATA minimum power profile select
echo "max_performance" > /sys/class/scsi_host/host0/link_power_management_policy
echo "max_performance" > /sys/class/scsi_host/host1/link_power_management_policy
echo "max_performance" > /sys/class/scsi_host/host2/link_power_management_policy
echo "max_performance" > /sys/class/scsi_host/host3/link_power_management_policy

# Hard disk Advanced Power Management (performance)
hdparm -S $spindown -B 255 $disk >/dev/null 2>&1

# CD-ROM polling disable
hal-disable-polling --device /dev/cdrom --enable-polling >/dev/null 2>&1

# Report high performance to the system
echo "high" > $perfile

echo "done."

Referring to the lowper script, what it does is to set the minimum power policy configuration for managing disks. This will be discussed in furhter sections. Then, the script disables the polling on the CD/DVD drive and finally it sets the maximum possible frequency to 800MHz, which is the minimum on my laptop. This gives me a much longer battery life.

On the other script, the highper, things are done in the same order but with reverse effects. The disks are set to use the performance settings, the polling on CD/DVD are enabled and the maximum possibl frequency is set to the actual maximum frequency allowed by my processor (2.26GHz). Now let's discuss part by part, which subsystems should be tuned, how and why.

Hard Drive Settings

Tuning the hard disk for power saving is not all about configuring certain settings for the drives, but also setting the applications' settings to not to use the disk or use it the least possible. The first improvmenet can be added by using the option noatime when mouting the file system. This option avoids certain writes on the meta-data when accessing any information in the hard disk. Moreover, if you are using ext3, you may want to mount the filesystem with the option data=writeback, which uses a special type of journaling where only the meta-data is being verified. By default, the ext3 filesystem performs journaling of all the data, which includes plenty of writes, but using the writeback type of journaling, we can avoid a huge amount of writes to the hard drive.

The next step to take is to configure the logging daemons to not to write much information on the hard drive. Logging daemons such as syslogd and ksyslogd are continuously watching the events on the system and writing messages to files in the hard drive. Certainly, this is quite interesting, but we may not need it if we are not using the computer as a server, and so we can probably deactivate many of these log writes.

Therefore, you can edit the file /etc/syslog.conf and change the second column, where the output file is specified for each type of event. Putting there /dev/null will make the syslog deamons to not to write any messages in the hard drive, thus saving some writes and therefore extra energy.

Another important task is to configure the program hdparm. This program is usually executed at boot time, and it sets certain options for every drive. The configuration file is at /etc/hdparm.conf. There we can set our customized options in order to squeeze the maximum juice from our hard drive devices. These are the options I use:

/dev/sda {
	read_ahead_sect = 2048
	spindown_time = 24
}

These options are set for the only disk I have in my computer. However, if you have other disks (e.g. sdb or hdb) you may want to set specific settings for each of the drives. The first option tells the system that, when reading some data from the hard drive, 2048 blocks should be read at once. Thus, if we need later some close information, it will be cached in the system, since it was already read when reading previous data. Afterwards, the spindwon option sets the time for putting the hard drive into low-consume mode. This value is a multiple of 5, so 24*5 means 2 minutes.

Another option that can be used with hdparm is -B N, where N is the mask mode for the Advanced Power Management. Setting this option to 1 makes hdparm using the most aggressive powersaving settings on that disk. On the other hand, putting this value to 255, makes hdparm to configure the hard disk for working in the highest possible performance profile. The syntax would be something like:

~$ sudo hdparm -B 1 /dev/sda

Finally, there are several tweaks that can be customized using the sysctl interface, thus telling the kernel how to behave when dealing with the file system. These options can be set any time using the sysctl command or placing them at /etc/sysctl.conf. My options are the following ones:

vm.laptop_mode = 5 vm.dirty_expire_centisecs = 60000 vm.dirty_writeback_centisecs = 60000 vm.dirty_ratio = 60 vm.dirty_background_ratio = 1 vm.swappiness = 10

The first option (laptop_mode) tells how long a write should be delayed before writing it to the actual hard drive. The default value is 1 (which is a multiple of 6 seconds), but putting 5 is safe, and delays the write for 30 seconds. Think that in the meantime, some operation could cancel this write and then there is no need to write the data anymore in the disk. However, having a low delay, the data could be first written in the disk and then deleted from the disk, which would result in two accesses, whereas we needed none when using a longer delay.

The dirty_* options are taken from the Internet and they are natural values for a laptop. These options also delay write accesses to the hard drive, resulting in a system where the hard drive is almost not touched for long periods of time (relatively talking).

Last, the swappiness option is used when utilizing the swap partition. This is less common in current computers, due to the availability of important amounts of RAM memory. However, it doesn't make any harm to configure it for a long value, where also the swapping information may be delayed (thus kept in the memory), increasing the memory pressure but keeping the hard drive untouched.

Wireless

If the hard drive is important for power saving, so it is the wireless card. Typically, we need to make use of the wireless card almost all the time, without having the chance to disable it using the radio kill switch. Nevertheless, there exists an option that can make the wireless much less power-hungry, thus awarding us with some minutes of extra battery. The command is the following:

~$ sudo iwpriv wlan0 set_power 6

This command will make the wireless card to enter in the lowest possible consume mode. However, 6 might be a number which is platform dependent, and so you should check the available numbers on your computer with the following command:

~$ sudo iwpriv wlan0 get_power

The command above will list you a number of possible values for power settings to you wireless card. You just have to make use of the most convinient for you.

Bluetooth

The bluetooth driver in the Linux kernel doesn't support yet the autosuspend option, and therefore we have to enable and disable it if we want to save some energy. The command to temporarily disable the bluetooth is the following:

~$ sudo hciconfig hci0 down

Like any other network interface using hciconfig and then 'up' or 'down', we can set the device in active or inactive mode, which will save us some extra minutes for our battery.

Other Devices

Normally, we will configure the hard disk and the network devices to consume less power. However, other devices are not typically configured for power saving, since they don't affect quite much the performance or battery life of the computer.

Nevertheless, it is important to search in the Linux kernel configuration options that are specific to certain drivers and that can make a device enter a lower-consume state automatically when they are not needed. This is usually carried out by the kernel, and hence there are no userland nor specific user options for configuring the power saving on these devices.

One of the greatest tools available for GNU/Linux to check the power consume per device and per process is powertop, an utility provided by Intel which is capable of telling us very detailed and fine-grained information about how processes affect the energy consume on our computer and how the kernel, and the system in general, should be configured in order to achieve the maximum power saving point.

In order to run powertop you must be root or use sudo. The first time you run it, it will complain about features that have not been enabled in the kernel and hence it cannot display certain information. However, once you go to the kernel configuration and enable the options that powertop told you, you will be able to see the power consume per device and process, including consume statistics and advanced options and suggestions for improving your personal computer. Quite a nice tool!

Considerations

So far, we have seen how to configure the ACPI system for saving some energy, many options for the hard drive and some options for wireless and bluetooth devices. That's it, in GNU/Linux the majority of energy saving is done through ACPI (on x86 architectures) and fine-tunning the hard drives.

One of the biggest considerations to be taken in account is the fact that running heavier software will make the computer consume more power. For instance, running a GNOME or KDE desktop will make the computer more power-hungry, since more tasks are running at the same time and the CPU needs to be active for longer periods of time. On the other hand, using tiny window managers such as Openbox will make the computer much lighther, thus consuming far less energy. Also notice that the more processes that are running, the bigger the possibility to write on the disk in smaller intervals of time, thus consuming again more energy.

Disclaimer

I would like to emphasize the fact that this article is missing a lot of fine documentation and that many details about specific hardware or software components might be missing, and they probably are. Therefore, I encourage you, the reader, to send me any feedback information or provide me with detailed data about how to configure some specific subsystems or any hardware device you may have been using.

Besides, the commands and programs presented in this article are used at your own risk, and I am not responsible for any damage or loss the following of this article might cause to your system.

References

Less Watts (Saving Power with Linux) [online]. Linux PowerTop
URL: http://www.lesswatts.org/projects/powertop/known.php
Accessed on 4th October 2008

www.claudiocamacho.org
Updated on Saturday, 04 October 2008 17:13