Kernel Korner - Extending Battery Life with Laptop Mode
Laptops give you the freedom to do whatever you want, wherever you want to do it. But when your battery runs out, the fun is over. Fortunately, there are a lot of ways to save power and make your battery last longer. For instance, you can lower the processor speed, dim the display's backlight and spin down the hard drive. The first two tricks work well on Linux, but until recently, spinning down the hard drive could be quite a struggle. Even if you could get the drive to spin down, it never would stay down long enough to save any power. This article explains how you can use Laptop Mode, a feature recently added to the Linux kernel, to spin down the drive for real. I talk only about Linux 2.6 here; a Laptop Mode is available in 2.4, but it is a bit different.
Let's do a little math to find out how much extra battery life you can get by spinning down the hard drive. A typical laptop on the market today has a lithium-ion battery with a capacity of 50–100 Watt-hours of power, which is good for two to four hours. Say we have a laptop with a battery of 50 Watt-hours. If the battery lasts for 3.5 hours with the hard drive on, then we can calculate the average power usage as 50/3.5 = 14.3 Watts. Say the laptop uses a typical laptop hard drive, which uses about 0.9 Watts in idle mode and about 0.3 Watts in standby. In theory we can reduce the power usage by 0.6 Watts, to about 13.7 Watts. This increases battery life to 50/13.7 = 3 hours and 39 minutes. The gain always depends on how much power you save relative to the total power usage. In our example, the spindown saves about 4% of the total power, so the maximum gain in battery life is about 4% as well.
So much for theory, I want to show you some real data. I borrowed a friend's Apple PowerBook G4, installed Debian GNU/Linux and the Linux 2.6.6 kernel and then did some experiments. I wanted to estimate the maximum gain in battery life and the time we needed between spinups to come close to that maximum. I expected a pretty large gain, because the laptop was equipped with a power-hungry 5,400 rpm drive and because I stripped the system of the X server and all dæmons. I wrote a benchmark program that always performs the same amount of disk I/O per hour, but with a configurable inactive period between I/O bursts. During inactive periods, the benchmark program spins down the hard drive. I ran the benchmark with a number of inactive period lengths, and I used the APM battery information to calculate the expected battery life.
I've run this experiment with the disk spun up all the time and with burst intervals ranging from 12 seconds to ten minutes. The results are illustrated in Figure 1. As you can see, as soon as you do I/O less than once every 30 seconds, you have pretty much saved all you can. This seems strange, because spinning up the disk costs a lot of power, right? No, actually, it doesn't. If the drive can spin up in two seconds, that takes about as much power as keeping it running idle for, say, eight seconds. So if you can spin that drive down for nine seconds, you've already saved some power. The 30-second burst interval already leaves room for a pretty long spindown, which is why it shows such good benchmark results.
Laptop Mode is a setting for the Linux kernel that changes how the kernel distributes disk I/O over time. Linux normally does disk I/O in small amounts, nicely spread out over time. But with all that I/O going on, your hard drive never gets a chance to spin down, wasting valuable power. For a laptop, disk activity must be concentrated into short stretches of time, with periods of inactivity between them, like I did with the benchmark. When you enable Laptop Mode, Linux does exactly that. You can get stretches of up to ten minutes without disk activity, which definitely improves your laptop's battery life.
Let's take a look at what Laptop Mode does to get that kind of I/O behaviour. To create periods without disk activity, we need to do as much as we can during the active periods. After that, we need to hold off disk I/O for as long as possible. During active periods, we do a couple of extra things. First, we perform some read-ahead; if that data actually is needed during the inactive period, we've saved a spinup. Laptop Mode sets the read-ahead to 4MB by default. Second, we sync everything to disk at the end of every active period. This keeps your data safe; when the drive has spun down, you can be sure that everything done up to the spindown is stored safely.
During an inactive period, writes are the only kind of disk I/O we can hold off. We can keep the unwritten data in memory for as long as we like or until we're out of memory. Unfortunately, this was not so easy for us to implement, because Linux submits write requests from many places. We needed to tweak all those places to hold off their writes.
The first and most important tweak has to do with modified or dirty data. Normally, when a cached disk page has been modified more than 30 seconds ago, it expires, and the pdflush dæmon writes it to disk. Fortunately, the expiry interval is configurable through /proc/sys/vm/dirty_expire_centisecs. Laptop Mode sets it to ten minutes so that changes stay in memory for up to ten minutes before they're written to disk. Because every active period is ended with a sync, the inactive period starts without any dirty pages. Therefore, during the first ten minutes of an inactive period, we can be sure that no pages are written back because they expire.
The second tweak concerns journaling filesystems, which do a lot of disk I/O themselves. On most of the journaling filesystems supported by Laptop Mode, a change to the filesystem triggers a write operation within five seconds. For instance, in the ext3 filesystem, a filesystem transaction has a maximum lifetime before it is automatically committed, and committing means writing to disk. This maximum lifetime can be configured using the commit mount option. By remounting the filesystem with this option set to ten minutes, we stop ext3 from committing transactions during an inactive period. Again, we start every inactive period with a sync, so no transactions are open when the inactive period starts. Laptop Mode extends a similar treatment to the other supported filesystems, ReiserFS and XFS.
The final tweak occurs in Linux's memory management. If a lot of memory is allocated during an inactive period, the memory manager eventually has to select some memory pages that need to be dropped. It is possible to select a page that needs to be written to disk before it can be dropped, for instance a modified disk page or a page that needs to be written to swap space. But then, it has to spin up the drive to perform that write, and we don't want that to happen. Andrew Morton tweaked the memory manager so that when we're running in Laptop Mode, the memory manager first tries to select pages that don't require a write.
Using these tweaks, Laptop Mode can create up to ten minutes without disk activity. When you're not changing any files at all, you can get even longer periods without spinning up the disk. After all, if there's nothing to write, there's no reason to spin up the disk. Unfortunately, when you've mounted the filesystems with the default options, things change by themselves; the filesystem records access times. Access times are updated even when you're only reading files, and they must be written to disk eventually. To avoid this problem, Laptop Mode remounts all filesystems with the noatime mount option. This makes them stop recording access times, so you actually can get more than ten minutes of time without disk I/O.
As you might have noticed, we're doing some things typically done from user space, such as tweaking /proc. In fact, we've split Laptop Mode into a kernel component and a user-space script. You can use the script to enable laptop mode, and it enables the kernel support by setting /proc/sys/vm/laptop_mode. It then remounts your filesystems and tweaks some other settings in /proc as well.