Core OS • OS X • 49:48
Mountain Lion includes several new power management behaviors that may affect the efficiency of your apps. Learn how to optimize your code for power use, how your code can influence system behavior, how to debug sleep/wake issues, and use existing tools to spot energy leaks.
Speakers: Ethan Bold, Soren Spies
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
So good morning. Thank you for coming to Power Management. My name is Ethan Bold. I'm on the CoreOS I/O Kit team, and I work on sleep/wake. And I'm going to talk to you about power management features and Mountain Lion that you should know about. And then after that, my coworker, Soren Spies, is going to come up, and he's going to tell you about some energy-efficient coding practices that you can use in OS X and in iOS. So let's talk about Mountain Lion. I'm going to talk to you about three things today. The first, power assertions. Power assertions are an API that your app can use to tell OS X when you need the system to stay powered on.
I'm going to talk about dark wake. That's a new system power state between asleep and fully awake. And then we're going to look at some debugging tools that will help you understand what's going on in your system with power assertions. Power assertions and sleep and wake and dark wake. So let's jump in and talk about power assertions. Power assertions allow your app to specify when you're doing user-requested work that you want to complete.
You can take a power assertion to prevent idle sleep. That is, to keep the computer awake and prevent it from idle sleeping while you're holding this assertion. You can take a power assertion to prevent idle display sleep. That is, to keep the display on as long as you're holding this assertion.
Power assertions are hints or suggestions to OS X. We can't guarantee that OS X will honor all power assertions. There's always things like the user closing of the lid, running out of battery, or overheating that will cause the system to have to sleep anyway, even if you're holding a power assertion. Not everyone should use power assertions. There's a few good reasons not to. You shouldn't use them if the user isn't expecting your work to complete.
If your work is resumable and the user is not waiting for it, then the system can fall asleep and wake up again and your work can resume after that.
[Transcript missing]
This is going to create our assertion. There's a couple of other APIs similar to this one that you can find in the header. First argument to assertion create with name is the assertion type. We're passing type prevent user idle system sleep.
We're passing an initial level, K-I-O-P-M assertion level on. I won't talk about it here, but there are some APIs you can use in this header to toggle the level of an assertion from on to off and off to on. You could do that if you wanted to create one assertion and reuse it.
But you can check those out for yourself. Next up, we're going to pass a descriptive name for this power assertion that we're creating. Here I chose to name the assertion "Processing Giant Files." I might be a video editing app that needs to edit 4 gigs of data, which could take minutes to complete, and I want that work to finish. So by calling it "Processing Giant Files," I let power users and admins and other developers and me know exactly why I'm holding this power assertion.
And finally, the API returns an assertion ID in the argument newAssertion. When this function completes, I'm holding a brand new power assertion. I've hinted to OS X that I want the system to stay awake, and I'm going to do my computation, whether it takes a few seconds or a few hours. And when I'm done, I'm going to call IOPM assertion release, and that lets go of this assertion I just created.
And it's very important to call IOPM assertion release as soon as you're done with your work, because that lets OS X reevaluate system sleep state and idle the system to sleep, if appropriate. So your app may hold several assertions at once. Realistically, you shouldn't hold more than five or ten at a time, but the upper limit is 1024.
[Transcript missing]
When you run Caffeinate, it takes an assertion. And when you kill Caffeinate, it drops that assertion. The way we're invoking it here is we're passing it the argument Make. Caffeinate is going to take that argument and run Make, and keep Make running, and let Make run until it completes.
When Make exits, Caffeinate will exit, and Caffeinate will drop its power assertion. So this could have been a build that took two hours, and Caffeinate held the Prevent User Idle System Sleep assertion in that time. Check out the man page for both PMSET and Caffeinate for other options.
Some of you may already be aware of, or may be using, the API IOCancel.com. This is a way to prevent idle sleep in OS X since 10.0. But we are asking that you move away from that and use I/O power assertions instead. Using I/O cancel power change and I register for system power to call I/O cancel power change doesn't give us the same amount of accountability for who's preventing sleep. Just like disk I/O, it's kind of sloppy. It doesn't let us detect exactly when you're done doing work and when we can go back to sleep. So for those reasons, please move on to power assertions if you're using I/O cancel power change.
We are not deprecating this API, cancel power change, right now, but we probably will do so in a future release. That was power assertions. Power assertions aren't new in Mountainside. They've been around since Lion. But they are increasingly important given things like the disk I/O no longer keeping the system awake. It's more important for you to tell us what you intend for sleep and wake to do. So next up, let's talk about dark wake.
Like I said, dark wake is a system state between sleep, where everything's off, and between full wake, where everything's on. When you're in dark wake, the CPU is on, the network is on, the disk is usable, any USB buses, firewire, thunderbolt buses, and any devices hanging off of them are powered and usable.
Also, DarkWake is Apple only. We aren't exposing any APIs to run in DarkWake or to access DarkWake in Mountain Lion. But I do want to talk about it, and I want you to know what DarkWake is and what it means for your Macs because you Because you may see it, you may observe your software running in dark wake.
Apple doesn't take any -- we don't take any measures to keep your code stopped. We don't turn off the CPU scheduler while we're in dark wake so your code could run. But you may find yourself running in a situation where the disk is -- I'm sorry, the disk is available, where the graphics aren't available and the audio aren't available.
And because we aren't exposing dark/wake to developers or even to many Apple internal apps, we've suppressed a lot of system-wide notifications, like sleep/wake notifications. We don't deliver those while we're in dark/wake. And network reachability. We don't expose a lot of network reachability notifications or state while we're in dark/wake. So you should be aware that your app could run in this situation. And your app should handle it gracefully if the network isn't available or if you can't talk to the Windows server or graphics or audio devices.
So we've had DarkWake in some form since 10.6, and we've been building on it with every release. Starting in 10.6, we used DarkWake to keep your system's network state up to date while your computer was asleep. And so your computer would be asleep but wake up every 90 minutes or so to refresh your DHCP lease, to remind your local Bonjor sleep proxy server that your computer exists and is reachable, and to tell iCloud and back to my Mac that your computer is reachable. Adding to that in Lion, in 10.7, we added a -- we started using Dark Wake to respond to environmental changes. That's plugging and unplugging the AC power, plugging in a new USB device.
So whereas in the past, when you plugged in a USB mouse, the system would wake up all the way into full wake and stay awake. Now what we do is we wake up into dark wake, recognize that USB mouse, reconfigure the USB mouse bus, and put the system back to sleep as soon as possible.
And adding to that in Mountain Lion, we have Power Nap. This is now a user-visible feature in Mountain Lion with a checkbox and energy saver to turn it on and turn it off. We're going to be using Dark Wake to wake up every hour or so on battery and on AC power and check your mail, check for new iCal events, check the App Store for updates and system updates. And to perform time machine backups and spotlight indexes. So that's Dark Wake. Please keep in mind that your software may very well run in one of these, in a Dark Wake state, and please handle that case gracefully.
So that was power assertions in DarkWake, and I want to talk briefly about some debugging tools that you can use to understand what's going on. I've got PMset on screen again.
[Transcript missing]
And this was a dark wake due to EHC1. I know that EHC1 is the PCI hardware code for the USB stack, for the USB bus. So this was probably me, the user, plugging in a USB keyboard. And the system woke up, recognized it, and went back to sleep. It goes back to sleep 19 seconds later. Again, due to a clamshell sleep, the lid is still closed, but it's returning to sleep from dark wake.
And a minute and a half after that, the user opens the lid and wakes the system. And you can see that the charge is 95% now, the battery charge. And the wake event is due to EC lid zero, and I know that's the wake up code for a lid wake. And I truncated the log right here, but the next sleep/wake event is probably 2662 seconds later on. So that's sleep and wake. Let's look at what taking assertions and releasing assertions looks like in NPM set minus G log.
This sample shows PID163 network browser taking a power assertion for the reason for the name AirDrop, and they used a very descriptive name that tells us very concisely what the network browser tool app was doing. And it held that assertion for 12 seconds. So that was probably me copying this very keynote presentation from one computer to to another over airdrop. Next, we can see that PID 5681 address book, address book source sync took a prevent user idle system sleep assertion for 22 seconds and then released it. Yeah, they were probably syncing address book data with iCloud.
So that's it for me. Thank you very much. And here's Soren Spies. Good morning. Thank you all for being here. My name is Soren, and I am an energy enthusiast. And this morning we're going to talk about energy for software. First of all, I'm going to tell you a little bit of Energy 101. One slide, everything you need to know to understand energy efficiency and the power-time trade-off. We're going to talk about the rationale, why we care about software and its energy efficiency.
And we have a good little home economics example for energy versus utility to kind of help you think about your software and how can you make your software more efficient. You've got to have a slightly different mindset when you are optimizing for energy efficiency versus time performance, although they're related, as you will see.
The last section of the talk is principles and techniques for debugging your software, finding idle energy leaks, and being as efficient as you possibly can be. So first of all, here's the Energy 101. Energy is very simple. Its power, in this case a 27-inch iMac, not at full screen brightness, draws 100 watts. You run that for two hours.
[Transcript missing]
products, and we want your products to also be efficient. So we're going to talk about how to make your software efficient. So one thing you may not have thought about, you may realize that you put your laptop to sleep when you're not using it and when it's asleep, it lasts a long time, especially our standby machines.
The ratio, very roughly, from being awake and idle to asleep is about 10 to 1. So you can leave your computer sitting there for an hour or 10 hours, and if it's asleep, 10 hours of battery disappears as about one hour. But what you may not realize is that while you're running, you're sitting there idle, there's also a 10 to 1 ratio between full out GPU, CPU, everything is going crazy versus idle. There's a big difference. Again, so from all the way like full idle to totally asleep is like 100 to 1 ratio. So you want to minimize your power consumption when you are running, especially when you're idle, because that's what you do most of the time.
Also, batteries are only so big, so you can only expend them. You can sort of -- you're going to use up that energy, you want to use it as coolly, lowest temperature, and as slowly as possible. So there's sort of a tradeoff between time and heat, and then what value is your software delivering? So here's just a little graphic to help explain.
First of all, we want to make the energy last. But even .1% CPU, if you look in activity monitor, you're like, oh, my software is barely doing anything. .1%. That's not going to help. That's going to be a .1% CPU. Depending on how it does it, it can actually be significantly elevating the power draw of the system, and that can have a very negative effect on your battery life. It can easily cost even an hour of battery life, even though it looks so tiny. I'll show you in a minute why that happens. So here's a graph.
This is showing sort of the all out, like maxed out machine, full bore. Batteries just like disappears in like one hour. Theoretically it's like a 7-hour battery, but you go all out and disappears in like one hour. So here's a graph. This is showing sort of the all out, like maxed So... that's not what we want.
Most users, they kind of have this experience. They're running a lot of apps, they're busy doing stuff, and their battery lasts, you know, five to seven hours, right? But ideally, if you're just, like, sitting there, you're, like, maybe running your word processor or something, you'd like to get, like, maybe ten hours of battery life if you could.
And so these bars all have the same area, and as we reduce the power, you can see the time jumps out. And we're not reducing the power very much, but, man, did you see that? We reduced it, like, two pixels, and it's, like, getting way out there. And this is what we're talking about, is get your software so it's really chill when it's not doing anything. When it is doing stuff, great, no problem, but when it's not, get it really chill.
And let's figure out how do we eke out these last few little bits of extra battery life so that instead of saying, well, I've got a bunch of apps running, so I'm only going to get four hours of battery life, you say, I've got a bunch of apps running, but they're all really good power citizens, really good energy citizens. And now I'm still getting a lot of battery life as if I was only running my word processor.
So this is going to be a little diversion. Bear with me. It is going to help you think about your software. A microwave appliance, very simple device, basically does two things. It can heat things, primarily food, and it has a clock. Turns out heating is about 1500 watts on the microwave.
And at least on my somewhat older microwave, it's not Energy Star labeled, it takes three watts just to operate the clock. Now, the clock itself is not consuming three watts. It's the power supply for the clock that's kind of radiating some heat. Well, it's converting 120 volts to whatever voltage the clock wants. So let's think about, remember, energy equals power times time. So here, those green spikes are the heating energy. Let's say I heat up some stuff three times a day.
I run it for about two minutes each. And then, but every single minute of the day, that clock is running. You see that down, you barely see it along the bottom, but there's just three watts along the bottom. So let's add up the energy. Energy is power times time. So here's a little kind of step graph.
This is just the heating energy, right? So we have, each time we use it, it bumps up. You know, here, use it, okay, that's great. Use it again, okay, great. Let's add in the clock, right? You can see that over time, that clock is slowly adding to the energy consumption. And it's actually, by the end of the day, there's a significant, you know, it's not just like a little bit of energy, it's a significant amount. In fact, 500 to 1 ratio between the heating energy and the clock energy, or sorry, heating power and clock power.
It's only a 2 to 1 ratio between heating energy and clock energy. So this is a critical thing to understand. The things that you do for short periods of time, the power matters, but the things that you do for long periods of time have a much larger impact on energy.
So we're going to talk about how to achieve that in a moment. For those of you who are sort of math-oriented, you can kind of see in my equation that the 1500 watts and the 1400 minutes, that's minutes in a day, is about the same. And then the 2 to 1 ratio comes from the 6 minutes total of the microwave versus the 3 watts.
So for your software, think about what your user wants. What are you doing for the user? What are you delivering versus any background activity costs? Because if those background activity costs are, you know, 50% of the cost of your software on the battery, you can do better. And we want to help you do better.
[Transcript missing]
You can also use Dtrace on the command line to get some stacks from your system. So this first example is I want to know when are those get time of day calls happening. And you can say just focus on my app and give me a user stack every time get time of day gets called. And you can go back and look and say -- you can also set a break point in the debugger and see why is this getting called. Then this is kind of the big hammer weapon.
I don't know how much you Dtrace, but you can basically say every single function call I want to know when it gets called. And you'll get the information about the function call getting called. You can filter this down a little bit once you get an idea of maybe what the most frequent ones are.
But this will definitely determine -- this is like the ultimate determinant of is your app idle? Is it running software or not? Is it running code? Are function calls getting called? And we also have both system trace and within system trace we have the system call instrument that can help you get back traces for these things so you can figure out where in your code this is happening. This is happening.
[Transcript missing]
Peripherals in particular are conservative. They tend to power up and then they kind of hang out for a while and then they spin down. And so ideally we want to tell them we're done. We're going to turn it off now. So often there's API for this, whether it's dropping an assertion like Ethan mentioned or a close or a release or a disable.
There are many different ways for the different frameworks to say I'm done with the camera. I don't need the GPS anymore. I have closed my networking connection. All of those things you can proactively kind of shut down and finish up with. On iOS in particular there's a UI kit background task completion that times out. Don't let it time out. Release it when you are done so that we can immediately go ahead and put the system to sleep.
As Ethan mentioned, we have both frameworks and iOS does this extensively depending on which framework calls are currently active. It will hold assertions on your behalf. OS X has a framework that allows you to do that. It has more direct access to the assertions. But you want to close those things, release those assertions, drop your references, et cetera, so that we can go ahead and say, oh, this software is done. Let's go ahead and power down.
So the first thing to check is first of all is your CPU still idle? A lot of times you do some work and, you know, idle, work, and then you kind of don't go all the way back because you left some timers running. You have some animations still on screen. So exercise your code and then analyze idle. First do your idle analysis when you launch.
But then also do a bunch of automated tests, run all your automated tests, and then see am I still idle or do I have stuff that's kind of running in the background. I often find that quitting and restarting an app will cause its CPU consumption to go down. And I'm, oh, you know, it's an opportunity for optimization. GPU mux on OS X, we have this two graphics processing units on some of our blocks. We have some of our portable products.
And the sort of the external one versus the one that's built into the motherboard chipset is more power hungry. And so we will switch between these depending on what you're doing. But there's a developer Q&A that makes sure that if your process is using the GPU, you do it wisely so that when these switches happen, you don't end up leaving both of them powered on.
There's a particular break point here. CGL bad application not mux aware lockdown. You can set that break point and see if you get called. But check out that Q&A. Finally, iOS has a wonderful energy diagnostic instrument. This does not give you back traces, but it does give you kind of a high level view of is the GPS turned on? Is the display bright? Am I doing network activity? And just kind of gives you a notion of you can run your software, you can see it kind of light up the machine, and then when you try to go back to idle, you can see where you were successful.
Did the machine idle back down? And you can also see how long it took in some cases. Maybe you didn't fully close things. Maybe you let something time out instead of actively closing it. But it gives you a pretty wide view of Bluetooth, sleep/wake, et cetera, et cetera, et cetera. So that is a tool that you can use for iOS particularly to see which parts of the system you left turned on.
[Transcript missing]