Hi everybody,
This is my experience with PowerTOP on my Macbook Pro Core2
duo. It's the recap of long hours of experiments that I
think may be useful to share with others, so that's why I am
posting it here.
I am no electronics engineer, hardware expert, or kernel
guru, just a regular Linux user with some programming
experience.
First, I noticed that my CPU consumes considerably more
power (an extra 0.5W) when running at the lowest speed
(1.00GHz) as opposed to when it runs at its native speed
(2.16GHz); it may be a hardware flaw (ACPI?) or anything
else, I don't know. But this taught me that I should not
take for granted that "slower" equals "less power". Running
the CPU at a slightly higher frequency, say 1.33GHz, does
not affect power consumption as 1.00GHz does. Who knows.
I also noticed that there is barely any difference in power
consumption no matter what the P state the CPU is running
at; indeed, from my tests, it looks as if a higher speed
(equal to the "rated" CPU speed) gives an overall reduction
of power drain. After observing that MacOS-X keeps running
the CPU at its highest clock 99% of the time, I wonder
whether cpufreq, in as cool and sexy as it is, does make any
sense at all (given the fact that it does introduce some
overhead). For me, it seems that it doesn't (even when I
adjust the minimum frequency so as to avoid the 1.00GHz
thing described above). My guess here is that a faster clock
allows the CPU to do its work quickly, and then sleep
longer. I may be wrong, and I would like to know whether
other people experience the same situation.
That said, my initial setup (runlevel 1, filesystem mounted
read-only, bare environment with only essential drivers
compiled inside the kernel, etc.) was giving me an average
power consumption of 18.3W, and around 16 wakeups/second.
The first candidate for reducing the number of wakeups, for
me, was usb_hcd_poll_rh_status(). From the kernel sources
(2.6.22-rc6), it seems as if a new interrupt-driven model is
underway, but apparently this is not implemented yet, and
drivers/usb/core/hcd.c (line 588) has a timer that fires
every 250ms: I started incrementing the timer a bit at a
time, and could not notice any problem (I cannot disable USB
entirely because my built-in keyboard is USB). Then I
increased the timer value up to a ridiculously high value
(20 seconds), and also wrapped it with round_jiffies().
After that, I could see a value of 1-2 wakeups/second, and a
reduced power consumption of approximately 0.3W.
I also tweaked a couple of other mod_timer() calls in the
kernel core, just to see the effects (though I must admit I
don't know what I am touching). An idle kernel, for me,
produces (still in runlevel 1) just ~1 wakeup/second (with
C3 residency times of ~850-1000ms).
So, my first conclusion is: there's some room for
improvement in the kernel itself, and I'm planning to
investigate how it is possible to bring this number down to
just 0.2-0.5 wakeups/second, or possibly even lower. My
impression is that there are some low-priority,
non-critical, timers that fire every now and then, and
fixing their behaviour should not be a daunting task: the
key thing here is not the frequency of those timers (how
many times per second) but rather the time *when* they wake
up the CPU: round_jiffies() is good enough to take care of
that.
Kernel configuration, too, has some impact. Selective USB
suspend (as suggested by powertop) accounts for about 0.4W
savings for me, and tuning options related to cpu and
architecture gives me another extra 0.4W.
The next steps will be to identify userspace code that
abuses timeouts: my first fix is for init itself, which
keeps waking up every 5 seconds for no apparent reason
(other than possibly recreating /dev/initctl if somebody
deletes it). My init has been running for a while now, and
it is no longer responsible for that 0.2 wakeups/second that
used to annoy me so much. Patch attached.
Andrea.
diff -ur sysvinit-2.86/src/init.c sysvinit-patched/src/init.c
--- sysvinit-2.86/src/init.c 2004-07-30 12:16:20.000000000 +0000
+++ sysvinit-patched/src/init.c 2007-07-16 00:26:41.000000000 +0000
@@ -2001,7 +2001,6 @@
void check_init_fifo(void)
{
struct init_request request;
- struct timeval tv;
struct stat st, st2;
fd_set fds;
int n;
@@ -2059,9 +2058,7 @@
/* Do select, return on EINTR. */
FD_ZERO(&fds);
FD_SET(pipe_fd, &fds);
- tv.tv_sec = 5;
- tv.tv_usec = 0;
- n = select(pipe_fd + 1, &fds, NULL, NULL, &tv);
+ n = select(pipe_fd + 1, &fds, NULL, NULL, NULL);
if (n <= 0) {
if (n == 0 || errno == EINTR) return;
continue;
_______________________________________________
Power mailing list
[email protected]
http://www.bughost.org/mailman/listinfo/power