Tuesday, February 21, 2023


Tags

Sleep Aid Icon

Sleep Aid 1.2 Energy Efficiency

What started out as trying to report accurate battery usage, resulted in reducing Sleep Aid's energy usage by 98%

Tuesday, February 21, 2023 - Sam Rowlands



How it began

Since early test versions of Sleep Aid (Jan/Feb 2022), I wanted to report the battery usage during sleep. In my mind, this was the best way to quantify the effects of the various sleep settings.

Everything I could find returned the value as an integer 0 ~ 100. However M1 based Macs, could sleep for 17 hours and the value wouldn't budge. I know it's using something during that time.

I stumbled upon "AppleRawCurrentCapacity", which gave me the mAh values of the battery. Except it wildly varied, some sleeps would burn a lot, while others would increase the capacity.

kIOPMPSInvalidWakeSecondsKey suggested the solution might be to wait for a period of time specified by this key, and try again. It didn't help, so I moved on.

New awakenings

At the tail end of 2022, Sleep Aid had gained quite a bit of traction. I was spending a lot of time looking at customer data, trying to understand what caused their batteries to drain, or their Macs to blind customers in the middle of the night. I had a much larger sampling of Sleep data, but battery usage was still all over the place. I began to wonder if it was influenced by something I don't know about...

Different Types of Insomnia

My gut told me that Network Insomnia used more battery than regular maintenance. Collecting the data into two categories and averaging it, appeared to confirm that. At least to start with, as I added more data, the results became almost identical. Either network insomnia doesn't use much more energy or the wildly varying battery measurements were messing with the data.

Something else...

What if I remove everything I know, and see what's left? There was a big 'ole hint in the power management messages. I see some system processes are switched in and out of "App Nap" during insomnia.

App Nap is Apple's mechanism for reducing CPU time to apps that you're not currently using. By reducing CPU time, it reduces energy usage. I'd expect during sleep, all apps are napped... But what if they're not?

The hunt begins...

We have a possibility that some apps are blissfully unaware the Mac is asleep and carry on wayward, how to prove this and importantly what to call 'em?

My name is Sam, but I don't have a brother called Dean, nor a Chevy Impala. I still have the internet and access to the lore. "Energy Vampires" seems appropriate.

To test this, I pragmatically measure an apps CPU usage during sleep. Most apps used less than 1.0%, but some were chugging as much 30%.

I found 'em, I discovered "Energy Vampires" on the Mac.

Embarrassment ensured

Amongst these energy vampires, was Sleep Aid.

Sleep Aid's CPU usage was consistently at 5%. The functions that I originally thought might be causing this are consistent in duration, which should make the usage fluctuate over varying lengths of insomnia...

There's one thing that coincides with this pattern, that's collecting the Power Management messages. Integrating my newly acquired vampire discovery skills into a sample application, revealed it was exactly this.

98% reduction in energy usage

Sleep Aid is currently built with Xojo, and I'm using their "Shell" class to capture the power management messages.

Swapping out the Xojo class for a NSTask class, not only resulted in a dramatic drop in CPU usage, it cemented the inefficiency of the Xojo class and proved NSTask as the replacement.

I found there were two possibilities when using NSTask, but I settled on the less efficient technique as it provided more reliable results over long periods of time, all while reducing CPU usage by 90~98%.

3 wins for the price of 1

On further investigation, the Xojo shell was incurring ~50,000 interrupts a minute, while NSTask was only 20 a minute. Because of the excessive interrupts, the macOS crash reporter was generating reports on Sleep Aid. Once the Shell class was replaced with NSTask, this stopped, saving more energy.

NSTask allows the message collection to be run on the M1 Efficiency cores, thus adding to the energy savings to be had.

I am using an older version of Xojo due to my disagreement with their current "direction", however my results have been reproduced with the latest version available at time of writing.

I have notified Xojo, provided them with my testing method and results. As of yet, I've not received an official response. I will update this article if that changes.

The NSTask code I wrote is available from this link https://ohanaware.com/appkit/NSTaskEfficiencyTest.zip

At this point I have zero belief that Xojo will improve their shell class.

In the end

Did all this work help to stabilize the wildly varying battery usage, err... Nope... But it did create a better version of Sleep Aid, that uses way less CPU and less electricity. I'm really pleased with this win, even if no-one else notices or cares.

A future update to Sleep Aid will also include the ability to hunt and subdue Energy Vampires.

Thanks to Howard Oakley from https://eclecticlight.co/ and Jon Gotow from https://www.stclairsoft.com/ for helping me with my wild theories.