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 may have transcription errors.
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 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. and you can take a power assertion to prevent idle display sleep. And 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, or 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. Some frameworks already take power assertions on your behalf, like NSURLDOWNLOAD will take a PREVENTUSERIDLESYSTEMSLEEP assertion as it begins a download and will release it when that download is complete.
And if the user is going to be active, sitting there at the computer while using your app, you don't need to take a power assertion because mouse activity and keyboard activity still keep the system awake and keep the system out of sleep. Remote connections like SSH, AFP, SMB are all already going to keep the system awake by holding power assertions when they have active users connected. And finally, capturing the display will prevent display sleep. Again, capturing the display is a-- you would do that with an API call to Core Graphics. that's different than just running your app in a full screen window. So I talked about two types of power assertions. The first is prevent user idle system sleep. When your app is holding this power assertion, OS X will keep the computer awake, not let it idle sleep. We will let the display sleep, though. This assertion is great if you're doing any background processing or image editing or compilation that the system should stay awake until it completes.
The other assertion type is prevent user idle display sleep. And it keeps the system awake, prevents idle sleep, but it also keeps the display on. So while you're holding this assertion, the display will stay awake in full wake. And there are great reasons to take this, like if you are displaying a video or displaying content to the user, or if you're displaying a presentation, like a keynote presentation. So let's look at the source code that you would use to take a simple assertion in your code. These headers are located in the I/O Kit framework in the file iopmlib.h. We define an assertion ID data type, and this is the unique identifier that's going to name the assertion you create. Here we're calling IOPM assertion create with name. This is gonna 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 four 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 re-evaluate 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 10 at a time. but the upper limit is 1,024.
And many apps on the system can hold many assertions simultaneously. When a lot of apps are holding assertions at the same time, OS X tries to honor the highest assertion requested of all of them. So apps die. Apps exit uncleanly. Apps crash. And when that happens, PowerD-- that's our OS X daemon that manages power assertions-- PowerD will notice that your app crashed and will clean up all of the assertions on your behalf. One of the biggest reasons that I'm talking about power assertions today is that we've totally revamped the way we're doing idle sleep in Mountain Lion. Starting in Mountain Lion, we are no longer paying attention to disk activity to prevent idle sleep. It used to be that we would wait for one minute of idleness on the disk, one minute without disk activity. before we would let the system fall asleep into idle sleep. And that was kind of messy. It was kind of lossy. We did not get a really good, tight boundary of when the user was active on the system and when your apps were active on the system by watching disk IO. So instead of that, we want you to take power assertions, if you need to, when you expect the system to be awake, and that will let us idle sleep a lot more accurately and tightly as soon as you're done doing work. So keep this in mind. If your app used to generate a lot of disk I/O and rely on that disk I/O to stay awake, you may need to look into power assertions.
So I want to show you our command line tool, pmset. Right here, we're passing it the argument -g assertions to get a system-wide snapshot of what the power assertions look like on the system at this moment. The first output is a list of assertions that could be active. And you can see that prevent user idle system sleep is the only assertion that's turned on. It's set to one.
And the app that's holding that assertion is Spotlight. It's PID29. They gave it a pretty descriptive name. It says com.apple.metadata.mds. So that means that Spotlight is holding this power assertion, and they're indexing metadata. Now, note that they used a reversed DNS name format for the -- for the name. You don't have to do that. We do record your -- your process's name separately. So we prefer a -- a more human-readable, descriptive name there. The other command-line argument for power assertions that I want to talk to you about is called Caffeinate. Caffeinate is a wrapper -- basically just a wrapper for that API call we looked at, IOPM assertion, create with name.
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 IO cancel power change. This has been the way to prevent idle sleep in OS X since 10.0. But we are asking that you move away from that and use IOPower assertions instead. Using IOCancelPowerChange and I register for system power to call IOCancelPowerChange doesn't give us the same amount of accountability for who's preventing sleep. And just like DiskIO, 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 IO 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 Mountain Lion. They've been around since Lion, but they are increasingly important. given things like the disk IO 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, fire wire, 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... 'cause you may see it, you may observe your software running in DarkWake. 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 DarkWake 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 DarkWake 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 DarkWake. And network reachability. We don't expose a lot of network reachability notifications or state while we're in DarkWake. 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. 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 check box 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, the app store for updates and system updates, and to perform time machine backups and spotlight indexes. Thank you. 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. The whole time your Mac is running, the whole time any Mac is running, we are logging significant system events, sleep events, wake events, settings changes to the ASL store database. And you can get a window into that, a historical view of what your system has been doing with sleep and wake by running PM set minus G log. and that pulls the logs out of the ASL store.
So on screen, I have an example of what the output of PMSET-G log looks like for a sleep and a wake. You can see here that the user put their system to sleep at about 10:57 p.m. by a clamshell sleep. That's closing the lid. The battery was at 11% charge at the time. And that last line indicates how long between this event and the next major power event in the log. So the system probably stayed asleep for 62,416 seconds. This line for wake requests will log if OS X or any apps requested that the system wake up at a future date. None did here.
And we can see that the next day at 4:18 p.m., the system did a dark wake. 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 a 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 2,662 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 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're going to 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. Because 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, That's 200 watt hours of energy. So the power is 100 watts, but that's at any moment in time. You do that over a period of time, and then you get energy.
Energy is what's in your battery. Energy is what we have to burn fossil fuels in many cases in order to create. And it is what we want to optimize for. It's not just power. Power is obviously related. It's one of the main components here. But there's also a significant time component. So why do we care? We have many wonderful devices, and they are mostly running on batteries. We want that battery life to be exceptional. We want it to be really long. We're trying to do our best at Apple to make super efficient products, but they're also very dynamic, and so they respond. When your software says, oh, let's do something, our hardware responds and says, okay, let's do it. But if it's not delivering value, then we're needlessly consuming energy from the battery.
Now, as I'm sure you've all experienced, when you do a significant amount of work on any compute device, basically when you're computing, you're turning stored energy or electrical energy into heat energy. And depending on how fast you do that, you get a different temperature on your device, the physical touching your device. So it will get warm. And that is not particularly pleasant for our users depending on how warm it gets. So we want to keep the work, if you're not doing anything important, especially nice and chilled out, literally chilled out so that our devices can stay nice and cool. Finally, if you do have some real work to do and you crank it up and you do that for a long time, devices that have fans will turn those fans on and they're already running most of the time, but they will actually get louder and louder and that's kind of unpleasant.
So basically we want the user experience long cool feeling to the device, and we want it to be nice and quiet. So that's the user experience portion. We also -- we want to tread lightly. We want to use energy wisely. We only want to consume what we need. Apple's trying to be very efficient in its -- 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 it kind of -- 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: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: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: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 You're like, oh, my software's barely doing anything, 0.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, you know, 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. Battery's just like, disappears in, like, one hour, right? Theoretically, it's like a seven-hour battery, but you go all out and disappears in like one hour. 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 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 roosted like two pixels, and it's like, whoomp, 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 1,500 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 while 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. 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, power and clock power, it's only a two-to-one 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 1,500 watts and the 1,400 minutes, that's in a day is about the same. And then the two-to-one ratio comes from the six minutes total of the microwave versus the three 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. So, all right.
principles and techniques for making your software an awesome energy citizen. So I have three principles. Call them absolute idle, extreme efficiency, and turn off the lights. This basically means don't do anything. It's the art of doing nothing. Then when there is something to do, and this should be for the user, not just because your software feels like doing something, go crazy. Just do everything you can at once so we can get it done as soon as possible. that, you know, power is -- you can have somewhat high power, but try to make the time component really, really short and then go back to really idle. And turn off the lights. Sometimes while you're doing stuff, you turn some things on and then you forget to turn them off. So you got to make sure that when you're done, you turn off the lights. So absolute idle, certainly you want to sort of just be blocked. You want to say, you know, next event. Cocoa, I'm waiting for my next event. Or sleep on some low-level system call if you're more of a background process. And you want real events to wake you up. You don't want timers to wake you up. You don't want to wake up to update your animations. You don't want to poll the network, especially if you're doing over a wireless network that can be quite expensive for your battery. So animations, network polling, timers, we want those things to go away. We want to help you find better ways to use system API to be completely asleep, not running your process at all, until a real event comes in for real work to do. So here's just a very simple kind of made-up example. I don't even know what compiles. But I see code like this all the time. So this example sleeps for one second and then checks to see if there's work to do. And it just keeps doing that over and over and over and over again. Every time it does that, it's like it scoops into the battery and, like, throws away a little bit of your battery life. So then here's another little thing that I see is once there is work to do, we start calling a little faster. Is it done yet? Is it done yet? Is it done yet? Is it done yet? Is it done yet?
And that is also extremely expensive. Let me show you why. So here's a graph, power versus time, and here's some of the code bits, right? So there's sort of the one-second polling is coming along, and oh, look, there's work to do. I'll see -- is it done yet? Is it done yet? Is it done yet? So -- and it's possible that that work is, like, waiting on the disk, right? It's not -- the machine's not even busy doing anything. So we aggressively power manage our processors and our disks and our memory, all of these parts of our system, which means in order to run a single instruction of your code, which may only take like a nanosecond, right, maybe your whole loop is only, you know, a microsecond, we have to bring that processor online. We have to power it up, and then when you're done, we chill out for a little while and then we have to power it back down again. All that red is pure overhead, and it's energy overhead, right? It's just needlessly operating it to check for something that didn't need to be done. And it gets worse.
Because not only does the CPU itself, the core, have to come power on and power off, but your memory controllers, your voltage regulators, your buses, your RAM, all of these things had been asleep, really chill, very low power, but suddenly they're like, oh, there's one instruction or 50 instructions, or it's a million instructions I need to run, even a million instructions doesn't take that long. We have to bring everything up and then we have to take everything back down. And you can see here on the right side that the -- when you're polling quickly, we don't turn off some of the memory controllers and buses and voltage regulators because they have to power up before the CPU core comes on and they have to power down after it. So there's multiple wakeups that happen just to get your little code running and then goes back to sleep. So this is a key message here that what looks like a tiny bit of code that your process is executing has an enormous energy cost for the system, especially if it's over and over and over again, if it's periodic. So let's look at some tools to get rid of these kinds of problems. So first of all, we can check for unexpected drawing. We can look for accumulating CPU time. We can check for system calls. System calls are nice because you generally want to park and just wait on a system call. You don't want to be coming out all the time. So that's a good place to look.
And finally, if you're really doing a great job, you can actually use Dtrace to look at every single function call that happens in your process. So here's a very simple example for drawing. There's a thing called Quartz debug for OS X, and there is a core animation tool that can do this for iOS. Basically, you check the little check box that says flash screen updates. So if you have your save dialogue and the save dialogue is pulsing, you'll see a little yellow blink. Look, something drew. And that is expected in this case because that thing is supposed to pulse when this is foreground. I believe when it's in background it doesn't do that anymore. You can look and see is the drawing expected. And if your thing is sitting there and maybe even in the background not doing anything, it probably doesn't need to be drawing. Next up, you can run top or you can use activity monitor. And top and activity monitor have this notion of CPU time. And that accumulates -- that's only that short time that your code actually ran. That doesn't count all of this other energy that was consumed to ramp up everything so that we could run your tiny piece of is there any work to do and then go back down. So I don't mean to just say your code because we also have these challenges. This is how we're trying to debug them. That CPU time will slowly accumulate if your process is busily doing stuff. I happen to use text edit while I was in the background and not too much excitement happening on the system. But even text edit, if you are switching apps, text edit gets a message every time the app switches. So it will slowly accumulate CPU time depending on system activity. If you do see your CPU time incrementing, you probably have enough going on that you can use something like the time profiler to kind of snapshot, what's going on now, what's going on now, what's going on now, and get some back traces and figure out what's going on. On the command line, there's the sample tool, but you can also use the time profiler in instruments on both iOS and OS X. File system tickles is another common place to look of how busy am I. You can run FSUsage, you can run file activity, you can run system usage for iOS. These will give you an idea of is my app talking to the file system. It also -- fsusage includes network activity.
System usage also includes -- I can't remember for sure. I doubt file activity does. But the notion is if I'm doing I/O, I am asking the system to do extra work for me, even though it's not accumulating in my process, it is causing the system to do things. And if -- when you're at idle, right, we want to be -- this is the art of doing nothing. You don't want to have any system calls, especially going out and doing I/O. So FSS usage is a great tool to figure that out and you can use these instrument tools to kind of get back traces and get a clue where it is in your code that stuff is going wrong. After FSS usage, that's only sort of I/O based system calls. We have SC usage, another command line tool. It targets a single -- you can run FSS usage on the whole system. SC usage targets a single process. The dash E flag will sort in order by which system call has been made the most. So in this case, you can see that in particular, mkitimerarm, psync, cvwait, and gettimeofday have all been called six times since I started this tool, but worse, they were called four, two, and one times, the parenthesized numbers. They were called very recently in the last sample. So it accumulates over time, but then it also shows you, oh, look, in the last sample these things got called. So if you do nothing else but go home and figure out why MK timer arm is being called for your software, you signed up for updates, you signed up for poll me, et cetera, if you can eliminate those calls, you will be making big progress on the art of doing nothing and staying very idle.
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 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.
So let's talk now about extreme efficiency. That way we talked about the art of idle and the absolute idle and the art of doing nothing. Now we're going to move over to extreme efficiency. We've got something to do. How do we want to do it? We want to do it as quickly and effectively as possible. So Apple has provided a lot of optimized library code that you can use to get your work done very quickly. That is going to use less energy because it's going to get done faster. You want to expose multiple threads. If you have a significant portion amount of work to do, go ahead and expose it using, you know, threads, GCD, NSOperation, whatever your favorite kind of matching API level is, go ahead and tell us about all the work that you have to do and we'll schedule it to the best of our ability on the system. There's also a Darwin background mechanism. There's a set priority to where you can basically say my process or my thread is not important. It's indexing. It's backing up. So go ahead and deprioritize it. Slow down its IOs. If necessary, in particular, we will run the CPU a little bit slower, at least on some systems, so that we will not make the system too warm. So that's a good way, if you do have long-running background work, you can mark it as background and then the system will do its best to efficiently optimize run time for it. A lot of code needs to do sort of background maintenance operations. As much as you can, batch those together and do them with user work. The user has asked your program to do something, Go ahead and do your maintenance operation at the same time. Don't just have it happening on a timer at a later point in time. Do them all together so that we can avoid, again, that sort of giant iceberg of, like, here's my little work that I did, but then I had to -- all this energy to get the CPU up and running. So here's a quick example I borrowed from the Accelerate talk.
Accelerate is a collection of very efficient low-level APIs that will speedily do math and other related operations. This is the FFT example, and here's a power energy graph, which is Accelerate framework versus sort of the textbook C implementation for how you do an FFT. So you'll notice Accelerate actually uses more power, right? It's a little bit taller up there, but it's so fast. It's nine times faster, and it uses one-eighth the energy because the time component is so much smaller. So, when you can, you want to use highly optimized libraries, and we're going to keep optimizing these for our future platforms. So, this is sort of just a picture of why the naive method, it may get their job done, but if you can get it done that much faster, you're using a lot less energy. Remember, energy is the area of these graphs. So, here's another example. I mentioned you want to expose multiple threads of operation or multiple operations that can happen concurrently. expose your parallelism.
So here we have not got too much red. This is actually not bad. CPU zero, busily working away. But there's quite a bit of blue, which is sort of a medium overhead that's servicing that CPU. It's got to keep all that stuff powered on so that one CPU core can go ahead and get some work done. So compared to this slide, here we managed to get all four CPU cores busy. This is a four-core example. We have, you know, from two to 16 cores, depending on which products you're -- one to 16 cores, depending on which products you're talking talking about. So if you can expose parallelism for -- you have at least one second of work to do. It's worth examining is there some parallelism that I can expose. When you expose parallelism, the system can schedule that across multiple CPUs and you'll notice there's a lot less blue and in particular the ratio of green to blue, you're being a lot more effective. The CPU time that you are running is more effective based on that overhead. Very specific suggestions, if you are doing graphics animations, you want to make sure you don't animate unnecessary. You don't want to make extra frames that never get displayed.
Really how many frames per second do you need for the goal? So depending on, you know, the standard or the display, there's a CV display link that will let you find out how fast the display is running. There's some sort of sample run loops that you can sign up for and say, hey, schedule me at this appropriate frequency for this refresh rate. Don't use OpenGL's open loop. You'll have a thousand frames per second but your display is only displaying 24. That's a lot of excess energy for rendering frames that don't get used. We also have some extensions called client storage and texture range which will help their Apple specific extensions. They will help you be more efficient in using the memory bus in particular. And finally, you might want to consider if you have just some background pictures in your -- you have a game and you're like, oh, is so beautiful, and there's some trees with leaves flickering, fluttering -- I shouldn't say flickering, fluttering, beautifully fluttering in the wind. You may not need, you know, 30 frames a second to keep those beautifully fluttering. You might be able to do 15 frames per second.
So you can kind of take your background elements and reduce the rate at which you're rendering. Because we're able to render those things quite quickly, and then the GPU can stay asleep in between frame updates. There is a Q&A technical doc, number 1385, which talks more about the rendering loops in particular.
I've been talking about both instruments and command line tools. In the iOS simulator, if you're clever, you can run some of the command line tools against your iOS apps. But instruments is the primary way to debug this kind of stuff when it's actually running on your iOS device. So for parallelism, we have a multicore instrument and a dispatch instrument, which run on iOS-- sorry, run on OS X, and possibly against the simulator. And then we have system trace and scheduling, which you can use on all platforms, which will show your parallelism. And you'll see, you know, "Oh, I have multiple threads that are running." Or maybe I have one thread that's running here, and then I have another thread that's running here. Maybe is there a way I could pull those together so they're running more concurrently at the same time? Also, performance -- traditional time performance is similar to energy. It's not the same, but when you are active, we want to get that time component down. So the faster you can get your work done, done, the less time you can spend at a high power state, the less energy you're going to use. So all these kind of traditional things like swapping and memory stalls and tiny little IOs, even lock contention and context switches, all of these things are a sign that you could be more efficient overall and you could be using less energy as well as getting your work done more quickly. Let's get to this final section. Turn off the lights. You did your work. You were very quiet. You were very responsive and you've responded to the user. Now it's time to make sure that we go back to idle.
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 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 it's an opportunity for optimization. GPU mux on OS X, we have this two graphics processing units on 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 that 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.
So Paul Danbold is our evangelist. I linked some documentation here, specifically OpenGL. I mentioned that tool Quartz debug. Quartz debug is no longer shipping with Xcode proper. You have to go to the extra downloads. I think it's an Xcode menu. It's like download more tools. The thing called graphics tools for Xcode contains that Quartz debug. And that's the one that detects like with a little flashing it will show you if you're drawing.
And then finally developer forums, you guys can help each other out. Thank you for coming, and I look forward to your answering your other questions. We have some related sessions that you can watch on video mostly. All of them, actually. Learning instruments, how do you use the performance tools, accelerate framework, how do you be super fast, and then a couple of app performance talks both on responsiveness, because, again, you want to be really idle, but then you want to very quickly respond, and then on graphics and animations, how do you efficiently do those graphics and animations. Please, thank you for coming again. Take the time to achieve absolute idle. Use those tools, figure out what absolute idle is. Do your real work efficiently. Try to work for the user and not for the network, not for a timer. And when you are done, turn off the lights. Remember, energy is power times time. So optimize for the long haul, what you're doing all the time, not what you're just doing for the short period of time. We want this optimized, but this long idle, it very low. That will make the battery last as long as possible. Thank you.