To avoid a lengthy intro, here is the thing: at some point OSX – and I’m talking specifically Snow Leopard 10.6.8 here – started feeling sluggish. The transitions didn’t feel smooth anymore and the general feeling was that OS was not as snappy as it used to be. Turns out all this has something to do with OSX’s built-in GPU power management, which reduces GPU clock speeds in order to save power. So what we want to do here is to turn this sort of throttling off and keep the GPU at its maximum speed at all times.
As all latest Macbook Pros, mine too comes with two built-in GPUs. It’s a mid-2009 model and has the less power consuming Nvidia 9400M and the more powerful 9600M GT. The idea here is to turn throttling off ONLY for 9600M GT and run it at its maximum speed when the computer is plugged into AC power. On the other hand, I want the system to use 9400M, which is less power consuming by design, when laptop is running on battery. Also the point is to keep the 9400M throttling scheme intact, because that’s what helps having an 8-hour battery life.
First, to have seamless switching between the two GPUs without logging out and back in, we will have to install a cool program called GfxCardStatus. It also features power-source based GPU switching, meaning that if we run 9600M GT on AC power and switch to battery power, the system will start using 9400M instead of 9600M GT. That’s the easy part.
Next: how to prevent 9600M GT from going into power-saving states and make it run at maximum power all the time? I found out that one way to do it is to disable a kernel extension AppleGraphicsPowerManagement.kext by moving it or renaming it (it can be found in /System/Library/Extensions/), but that disables throttling on both GPUs and we are left with no power saving benefits on 9400M; having no GPU throttling on 9400M cuts battery life from 8 hours to 4 hours, which is definitely not an acceptable option.
Let’s get back to AppleGraphicsPowerManagement.kext. Locate this file (and make also a backup copy of it), right click on it and select “Show Package Contents”. Find file Info.plist and open it with an appropriate editor (you will need Property List Editor from Developer Tools, PlistEdit Pro or a similar program that allows editing of .plist files). Within this plist file, navigate to IOKitPersonalities, AGPM and then find the corresponding model of your Macbook Pro (mine is MacbookPro5,3). It reveals settings for IGPU and GFX0 and LogControl. Turn LogControl to 1 (we will need this to monitor changes of GPU power states in Console). It doesn’t take much to figure that IGPU stands for integrated GPU, 9400M in my case, and GFX0 stands for 9600M GT.
Look in “Heuristic” – there are settings for Threshold_high and Threshold_low. They are not very self-explanatory, but some people on some forums have figured out that state 0 is the state of maximum power (highest GPU clock, memory and shader speeds) and state 3 is the state that saves most power (lowest clocks and voltage).
So the trick here is to set thresholds for going into power-saving states 1, 2 and 3 impossible to reach. The easiest to do so is to set their thresholds above 100.
Original settings, GFX0:
And now modified settings, GFX0:
Explanation: just added “1″ before an original number, so for instance, 65 becomes 165, just for reference, otherwise it doesn’t matter which number you use as any number above 100 will presumably do just fine. Also, power state 0 is the state of maximum power and I have set its Threshold_Low 0 and Threshold_High 90. The following state, state 1, had in its original settings Threshold_Low 68 and Threshold_High 65 (inverted, I know, odd, I know!), but I just simply bumped them to Threshold_Low 168 and Threshold_High 165.
When you finish editing, save the Info.plist. May require some permission acrobatics on your side, but once you get the modified Info.plist saved in the kext package, you will also have to repair permission on the modified kext, otherwise it might not load at startup. You will need Kext Utility for that. I used version 2.4.2 for Snow Leopard and 64-bit kexts. Run Kext Utility and wait one or two minutes for it to repair permissions in the Extensions folder. Then reboot the machine.
Logged back in, let’s check if everything works as planned. At this point I assume you have already installed GfxCardStatus so we can switch between the two GPUs on the fly.
First check System Profiler > More Info > Extensions to check if our modified kext has been loaded. If you see AppleGraphicsPowerManagement.kext there, it’s been done. Now let’s check how our power state changes are being logged and view the log in the Console. In Console, select “All messages” and filter strings matching “AGPM”. Now, if you are running 9400M (IGPU), you should be seeing quite frequent power state switching in the Console. Now switch to 9600M GT (GFX0) via GfxCardStatus. Then run Exposé repeatedly for 5 to 10 seconds. What you should be seeing in the Console is that GFX0 has been set to the highest power state (state 0) and remains there without any further switching. The last message you should be seeing in the Console (unless you switch back to 9400M, of course) should be something like:
AGPM: GPU = GFX0 G-state set to 0 from 1, ControlID = 17
Noticed how more fluid OSX user interface is now? Good. Now if you switch to battery, the GfxCardStatus should automatically switch to 9400M and you should be getting the same long battery life as before (6-8 hours).
If you feel these power state numbers (0,1,2,3) are too abstract, you can do your own checking of GPU power states translated to more realistic numbers with Nvclock. Nvclock (Linux utility that has recently been ported to Darwin/OSX) will reveal actual clock speeds (core/memory/shader) you are currently running. Explaining Nvclock is a bit beyond this tutorial, suffice it to say that I’m running 9600M GT at maximum speeds 540/792/1350 (540 MHz core, 792 MHz memory, 1350 MHz shader). These numbers reveal an interesting fact that Apple Nvidia Driver runs the GPU at slightly higher speeds than factory settings (which are 500/792/1250). No overclock to brag about, but fine by me, anyway.
While this sorting of hacking works just fine in my case, remember you are doing this at your own risk, and make backups beforehand.