Infinite Loop —

OS X 10.9 Mavericks: The Ars Technica Review

No longer an apex predator, OS X takes some time for introspection.

App Nap Policy

Right about now, you may be worried that Mavericks is going to make your Mac feel slower by starving all your applications of resources. But remember that the goal of App Nap—and Mavericks as a whole—is to extend battery life, yes, but also to improve responsiveness.

Rather than picturing App Nap as an energy miser, throttling all your processes to conserve energy, think of it as a guardian, ensuring that whatever you’re currently doing has access to as many system resources as possible. Success or failure comes down to the question of which applications should nap and when.

The policy in Mavericks is conservative. First, only normal Cocoa applications are eligible for App Nap. As mentioned earlier, this is true regardless of whether an application has been updated for Mavericks. The Cocoa framework itself makes several private system calls to tell the operating system that the process associated with an application is eligible for App Nap.

A new checkbox in the Finder’s Get Info window allows the user to disable App Nap entirely on a per-application basis—but only for applications that are not linked against the OS X 10.9 SDK. Developers who use the Mavericks SDK are expected to exert more fine-grained control over how App Nap affects their applications by using the new App Nap API.

Though Cocoa applications are signed up for App Nap by default and must opt out if they don’t want it, the existence of the aforementioned private system calls means that any other kind of executable that is not a normal GUI Cocoa application is not eligible for App Nap.

In fact, Cocoa applications that are not “foreground” applications (i.e., that do not have an icon in the Dock—see the LSBackgroundOnly or LSUIElementInfo.plist keys for examples) are also not eligible for App Nap. (There are other energy-saving strategies for background applications; more on those later.)

For all applications that are eligible for App Nap, Mavericks applies a set of heuristics to determine when it’s safe and appropriate to put an application down for a nap. Several factors influence this decision: application window visibility and drawing activity, audio playback, user input event processing, and the use of the existing power assertion APIs.

One of Apple’s demos in the App Nap session at WWDC featured a Cocoa implementation of the classic xeyes application. A pair of simply rendered eyeballs whose gaze follows the cursor hardly seems like an energy hog, but it’s exactly these kinds of innocuous applications that can end up using far more than their fair share of system resources. Xeyes must track the mouse cursor constantly, even when it’s not the front-most application, and it must continually redraw its interface in response to these mouse movements.

Sure enough, the new Energy Impact column in Activity Monitor—a composite, unit-less estimate of an application’s energy usage over time—shows that a pair of mouse-tracking eyeballs can be surprisingly taxing. But with the default App Nap heuristics, dragging another window on top of the eyeballs, obscuring them completely, eventually causes the application to nap and its Energy Impact to drop to zero.

The exact weighting of the factors that influence App Nap will no doubt change as Mavericks matures. A completely hidden application is an easy call, but in the general case, it won’t always be so simple for the OS to understand which activities are important to the user. When Mavericks is forced to guess, it tends to err on the side of leaving the application unmolested. But Apple would like it if the operating system didn’t have to guess, which is why it provides several new APIs that allow developers to tune their applications for energy efficiency.

But before considering those, it’s worth noting that there’s a lot that developers can and should do to make their applications better citizens even when they’re not napping.

Energy best practices

One way to implement the xeyes demo application described earlier would be to periodically poll for the position of the mouse and then update the eyeball graphics to reflect the new cursor position. For smooth animation, this polling would have to be done at least 20 to 30 times a second.

Unfortunately, polling is one of the least efficient ways to accomplish this task. Even when the cursor isn’t moving at all, the application is checking and rechecking the mouse position many times a second—and possibly redrawing the eyeballs each time if the developer isn’t storing the previous state for comparison purposes.

OS X offers a much more energy-efficient global event monitoring facility. (This is not new in Mavericks.) The operating system is already tracking the cursor; there’s no need for individual applications to do so as well. The application merely needs to register its interest in the cursor position and the OS will notify it when the position changes. No polling needed. This means that the xeyes application’s CPU usage can drop to nearly zero when the cursor isn’t moving, even when its window is not obscured and the application is not napping.

This is the ideal: when an application isn’t doing anything useful, its CPU usage should be as close to zero as possible. To achieve this, Apple discourages all forms of polling. Nearly every interesting event on the system can be delivered on demand to interested applications: FSEvents for file system changes; GCD's dispatch sources for file and network I/O, process creation and destruction, and signals; semaphores and locks for process synchronization.

Once an application has excised all forms of polling, it’s time to consider what else can be done in Mavericks to become even more efficient.

John Siracusa
John Siracusa has a B.S. in Computer Engineering from Boston University. He has been a Mac user since 1984, a Unix geek since 1993, and is a professional web developer and freelance technology writer. Emailsiracusa@arstechnica.com//Twitter@siracusa