PodSearch

Under the Radar

317: Optimizing for Battery Life

 

00:00:00 ◼   ► Welcome to Under the Radar, a show about independent iOS app development.

00:00:03 ◼   ► I'm Marco Arment.

00:00:05 ◼   ► And I'm David Smith.

00:00:06 ◼   ► Under the Radar is usually not longer than 30 minutes, so let's get started.

00:00:09 ◼   ► So today I want to talk about power, or in the context of the ways we use it, battery life

00:00:15 ◼   ► is probably more specific because we're not particularly – like that is the limiting

00:00:20 ◼   ► factor for a great many of our apps and the way that they get used, especially for things

00:00:25 ◼   ► that we both make, which are long-lived, long-run applications.

00:00:29 ◼   ► So if someone might use Pedometer++ to go out for an all-day hike, or they might open

00:00:35 ◼   ► Overcast and listen to a podcast while going out on an all-day hike.

00:00:39 ◼   ► And so in both of those cases, battery life and power consumption become an important aspect

00:00:45 ◼   ► of the user experience.

00:00:46 ◼   ► And battery life and power consumption are just a very difficult and challenging thing to optimize

00:00:53 ◼   ► and to get right in a way that is sometimes – I personally find very frustrating, but

00:00:58 ◼   ► it's something that I've been working on a lot recently.

00:00:59 ◼   ► Like in the last few months, I've been working on a mode in Pedometer++ that's focused on

00:01:04 ◼   ► sort of long endurance days.

00:01:06 ◼   ► So like being able to go out and track a workout for maybe for 20 hours, that's a very different

00:01:11 ◼   ► thing than if you're going out for a couple of – you know, like a 20, 30-minute run.

00:01:16 ◼   ► And so I've been doing a lot of work on battery life and power management and sort of – it

00:01:21 ◼   ► seemed a good topic to discuss.

00:01:23 ◼   ► I think I have some – it's like some hints, some tips, some pitfalls, some frustrations.

00:01:27 ◼   ► There's just a lot of things that kind of go into this because it's not as straightforward

00:01:31 ◼   ► as some of the other optimizations we might be doing where it's very easy to just open

00:01:36 ◼   ► instruments.

00:01:36 ◼   ► You run it.

00:01:38 ◼   ► You run your app with instruments connected, and you can run the time profiler, and you'll

00:01:41 ◼   ► see where your app is spending the most time.

00:01:45 ◼   ► And obviously that's related to power and battery consumption, but the power and battery

00:01:49 ◼   ► implication of just using a lot of CPU is more nuanced and complicated.

00:01:54 ◼   ► Because fundamentally, I think the thing that's challenging is ultimately power consumption

00:01:59 ◼   ► is going to come from two things.

00:02:02 ◼   ► One, the most obvious, is that it's just the work you're doing on the CPU, the GPU.

00:02:06 ◼   ► Like, your app is, you know, doing something.

00:02:09 ◼   ► That's what it's doing.

00:02:10 ◼   ► And that work will use power.

00:02:13 ◼   ► Just fundamentally, that's the nature of electronics and how these things work.

00:02:17 ◼   ► And the other place you'll use power is if you are ever transmitting or receiving anything,

00:02:22 ◼   ► whether that be sound, you know, photons from the display, Wi-Fi, GPS, any of these kinds

00:02:28 ◼   ► of things that are sending or receiving any kind of data, those things are using power.

00:02:32 ◼   ► And fundamentally, improving and extending the battery life of your app and reducing its

00:02:38 ◼   ► power consumption is fundamentally going to be about doing less of one of those two things.

00:02:42 ◼   ► Like, there is no magic other way to do this.

00:02:45 ◼   ► It's just you have to either do less work, and that will get one side of your power consumption

00:02:51 ◼   ► down, or you need to transmit or receive, you know, less.

00:02:55 ◼   ► Whether that be, you know, the way in which you are gathering, say, like, GPS data.

00:02:59 ◼   ► So that's very relevant for Pedometer Plus Plus.

00:03:01 ◼   ► I've done a lot of work on that.

00:03:03 ◼   ► Or in terms of Pedometer Plus Plus, it's dealing with, like, sending and receiving of light from

00:03:07 ◼   ► the heart, you know, the heart rate sensor on the Apple Watch is a fairly meaningful, you

00:03:13 ◼   ► know, consumer of energy.

00:03:16 ◼   ► And those ones particularly are challenging because they run into sort of physics limits, you know,

00:03:23 ◼   ► in the way that, like, if someone's playing a podcast from a phone speaker, if it's oscillating

00:03:28 ◼   ► air back and forth from the, you know, from the iPhone's speaker, that oscillation is taking

00:03:33 ◼   ► energy.

00:03:33 ◼   ► And there's a certain amount of, there's nothing you can do about that directly.

00:03:37 ◼   ► And so in that case, you're kind of stuck that it's going to use a certain amount of

00:03:40 ◼   ► sound energy to do it.

00:03:42 ◼   ► But there are things we can do on the consumption side.

00:03:45 ◼   ► And I think the process of finding a good fit for this is just, it's a challenging road

00:03:49 ◼   ► because inevitably in this, your job, you know, your app has a job to be done.

00:03:54 ◼   ► And so you need to do that job.

00:03:58 ◼   ► You have to see, like, the easiest way to use no battery is to do nothing.

00:04:01 ◼   ► That's not particularly helpful.

00:04:03 ◼   ► So finding the line between actually doing something useful and not being overly zealous

00:04:07 ◼   ► and, you know, using too much of the user's battery life and then them being frustrated,

00:04:11 ◼   ► you know, because they wanted to listen to a podcast for 10 hours and it ran out of battery

00:04:15 ◼   ► at nine.

00:04:15 ◼   ► Yeah.

00:04:16 ◼   ► I mean, you know, the easiest way to have, you know, impressive battery life for your app

00:04:21 ◼   ► is for people never to launch it.

00:04:22 ◼   ► So, which is great.

00:04:24 ◼   ► Like, you know, yeah, most people who download your app eventually don't launch it anymore

00:04:27 ◼   ► if they ever did.

00:04:28 ◼   ► So, you know, this problem does solve itself, but more seriously, and I think it's important

00:04:33 ◼   ► to recognize too, like, there's a lot of different patterns of usage of apps and, you know, sometimes

00:04:40 ◼   ► and there's also what people expect of, you know, apps and their power consumption.

00:04:46 ◼   ► Those don't always necessarily line up and you have to kind of have reasonable expectations

00:04:51 ◼   ► for what is realistic for your app in terms of power efficiency.

00:04:56 ◼   ► Like, you know, in terms of, you know, if you have, I think some kind of, you know, common

00:05:02 ◼   ► utility app where it doesn't really do anything in the background, there is occasional need

00:05:07 ◼   ► to launch it, interact with it for a relatively brief time, and then close it.

00:05:12 ◼   ► In that kind of scenario, you can do basically whatever you want and it doesn't matter.

00:05:17 ◼   ► Like, it's not, like, unless someone's going to be spending a very long time in your app,

00:05:23 ◼   ► it's probably not going to be possible for it to do meaningful damage to their battery

00:05:27 ◼   ► life, even if you're, like, running all the radios and the GPS and everything.

00:05:31 ◼   ► Like, you know, there's only so much you can do in a minute or two.

00:05:34 ◼   ► But where this becomes more important is, you know, background tasks especially, or if you,

00:05:42 ◼   ► if somebody is in constant interaction with the app.

00:05:45 ◼   ► So, for instance, if, you know, if you have, like, a navigation app, that's probably going

00:05:48 ◼   ► to be on screen for extended times.

00:05:50 ◼   ► Certainly, you're going to be probably using the GPS radio.

00:05:53 ◼   ► And there's all sorts of, you know, in that kind of case, there's all sorts of little, little

00:05:58 ◼   ► tricks you can do to reduce your power consumption.

00:06:01 ◼   ► Like, with GPS, for instance, you can, you can reduce the precision that you need or the update

00:06:05 ◼   ► frequency, core motion and core location.

00:06:08 ◼   ► Like, there's all these different parameters you can set to, to make that, you know, more or

00:06:13 ◼   ► less efficient.

00:06:14 ◼   ► You know, basically, when you're looking at power efficiency, the major areas that matter

00:06:20 ◼   ► a lot are screen brightness, radio and GPS usage, which is a radio technically, but yeah.

00:06:28 ◼   ► So, screen brightness, radio usage, and CPU usage.

00:06:31 ◼   ► Like, that's, and GPU, of course, you know, but so, you know, processor usage.

00:06:34 ◼   ► Those are the major areas that, that matter a lot.

00:06:39 ◼   ► What surprised me about overcast development is that I, I found another area, as you mentioned

00:06:45 ◼   ► a minute ago, that matters a lot, which is speaker usage.

00:06:48 ◼   ► Like, if somebody's using the built-in speaker to push that air, to make that sound, that surprised

00:06:54 ◼   ► me when I learned that that actually was a pretty big power draw.

00:06:56 ◼   ► And the way I learned that was, it was not possible to learn that through any kind of tooling.

00:07:03 ◼   ► There is no instruments simulator or Xcode meter that tells me how much power the speaker

00:07:09 ◼   ► is using.

00:07:10 ◼   ► The way I learned that was, a long time ago, I ran a test.

00:07:13 ◼   ► I was curious to see, like, you know, what, what I was expecting to see was how efficient

00:07:21 ◼   ► or inefficient AirPlay versus Bluetooth would be versus built-in headphones.

00:07:26 ◼   ► Like, that, that was what I expected to find.

00:07:28 ◼   ► And what, and what I expected to find was that using the Wi-Fi radio, which is AirPlay, was

00:07:33 ◼   ► going to be less power efficient or more power hungry than using Bluetooth.

00:07:38 ◼   ► And I expected both of those to be more power hungry than using the built-in headphone jack

00:07:44 ◼   ► to power headphones directly.

00:07:45 ◼   ► And what I found instead was, yeah, those matter.

00:07:48 ◼   ► But if the phone is sitting around beaming stuff wirelessly to something else, that's

00:07:54 ◼   ► actually pretty efficient for audio data.

00:07:57 ◼   ► What I found was that the, the speaker in the phone by far was the largest power drain for

00:08:06 ◼   ► overcast.

00:08:06 ◼   ► Like, if you play out of the built-in speaker, it uses way more battery power than if you are,

00:08:12 ◼   ► you know, sending it to headphones or speakers in any other way.

00:08:16 ◼   ► So that's something that, like, I, there was no way for me to find that other than just

00:08:21 ◼   ► like, all right, set up some tests, like, you know, make a test playlist, you know, play

00:08:26 ◼   ► it from the beginning and just have it just go for hours and hours and hours.

00:08:30 ◼   ► I turned off sync, you know, all that stuff, but like, you know, try to control it as best

00:08:34 ◼   ► as I could.

00:08:35 ◼   ► And it took, you know, like a week or two to run these tests.

00:08:38 ◼   ► And, but eventually, you know, I got my results.

00:08:41 ◼   ► And a lot of times that's just what you have to do.

00:08:43 ◼   ► And like, you know, just like performance testing, a lot of times when you do performance

00:08:50 ◼   ► testing, you know, you're, you're doing the CPU time thing with instruments or whatever.

00:08:53 ◼   ► A lot of times things that you think will be really inefficient are actually fine.

00:09:00 ◼   ► And you're spending a surprising amount of time or something as surprisingly costly that

00:09:05 ◼   ► you wouldn't have guessed would be.

00:09:06 ◼   ► And that exact same pattern holds in my experience for any kind of power and battery testing too.

00:09:13 ◼   ► And there's all sorts of ways that you can, you know, unknowingly waste power.

00:09:18 ◼   ► Like, like one of the common things is if you have some kind of internet connection requiring

00:09:24 ◼   ► operation, say like a background sync.

00:09:27 ◼   ► One of the ways that, one of the common pitfalls for that that I have found is what happens if

00:09:32 ◼   ► the sync fails?

00:09:33 ◼   ► And this can happen, for instance, if the person is like on a, on a subway and they lose their

00:09:38 ◼   ► connection for a few minutes or they're just, you know, they're hiking in the mountains

00:09:41 ◼   ► and they're offline, you know, what happens if the person's offline and some operation

00:09:47 ◼   ► in your app tries to use the connection?

00:09:49 ◼   ► What can happen is that can start going in a loop, just trying to hammer it over and over

00:09:56 ◼   ► and over again, making that request over and over and over again, which can not only make

00:10:01 ◼   ► the radios keep trying to connect, but can also burn CPU power by a lot.

00:10:05 ◼   ► And so there's situations where like you might not even realize like, oh, my app seems really

00:10:11 ◼   ► efficient, but if you're offline, it turns out you like power usage spikes and you might

00:10:16 ◼   ► never know that in your testing unless you're doing offline power testing somehow, which is

00:10:20 ◼   ► not a super common thing.

00:10:21 ◼   ► I don't think people test for, but like there's all sorts of surprises when you do power testing

00:10:26 ◼   ► that you don't realize like, oh, if I, if this weird condition happens, this will infinite

00:10:32 ◼   ► loop or this process will spin forever or it'll, it'll keep trying to do this thing.

00:10:36 ◼   ► So there's all sorts of things like that.

00:10:38 ◼   ► But then you have to contend with, even if you do a really good job of power optimization,

00:10:44 ◼   ► if your app is inherently doing something that requires a lot of power that the user has explicitly

00:10:52 ◼   ► asked you to do, whether that's playing podcasts very loudly out of the built-in speaker or just

00:10:58 ◼   ► using an app constantly with a screen on that happens to use, you know, the network

00:11:02 ◼   ► or GPS, like if, if that's what your app is doing, it's going to use a lot of power and

00:11:07 ◼   ► people, people are going to go into that battery section of their, of their settings and they're

00:11:10 ◼   ► going to see your app on top, even if they were using it that whole time.

00:11:14 ◼   ► So to some degree, this also creates marketing challenges or user support challenges in the

00:11:20 ◼   ► sense that like people, even if people like, you know, spend the energy knowingly with your

00:11:27 ◼   ► app, they will still blame you if it's inefficient, even if there's nothing you can do about it.

00:11:33 ◼   ► So there are, there are a lot of, a lot of, um, you know, sprawling places that, that power

00:11:38 ◼   ► testing and power mindfulness can take you.

00:11:42 ◼   ► Yeah. And I think in that there's this funny aspect of, yeah, like there, there's a fundamental

00:11:48 ◼   ► limit that you run into with power, power efficiency testing. Like at a certain point,

00:11:53 ◼   ► this is at least has been my experience is like, I've done a bunch of things and I think there's

00:11:57 ◼   ► some tools that I've, or strategies I've taken that I think would be useful to discuss, but broadly

00:12:01 ◼   ► it's like there's at a certain, you will inevitably hit this point that this is just like, this is the

00:12:06 ◼   ► floor and you can't go any lower. Um, and that is frustrating insofar as if that number is

00:12:11 ◼   ► too high and you're going to either have to diminish the user experience in terms of do

00:12:16 ◼   ► something different. Like that was ultimately like in the case of Panometer plus plus, what

00:12:20 ◼   ► I found is that if you run, you know, essentially continuous GPS and all of the workout tracking

00:12:26 ◼   ► stuff that you can do on an Apple watch, it is as far as I can tell, not possible to get

00:12:31 ◼   ► the sort of the 20 hour goal that I was trying to get on my Apple watch ultra. Like it was just

00:12:36 ◼   ► not possible that if in the way I determined that is that I built.

00:12:40 ◼   ► A stripped down version of my app that did nothing but those two things using just the

00:12:46 ◼   ► system APIs as basic as I could make it and ran that. And like, so at this point I'm confident

00:12:51 ◼   ► that it's not, you know, Swift UI getting into a funny state and using lots of data or other

00:12:57 ◼   ► background processing or refresh, you know, things. It's like as minimal of an app as I possibly

00:13:02 ◼   ► could. And I ran it. And like, at that point I determined this is the floor. If you do this

00:13:07 ◼   ► and this and this, it is going to take at least this amount of battery to do it. And so like

00:13:11 ◼   ► in my case, I've worked out, well, what if I don't do this? What if I do this? You know,

00:13:15 ◼   ► every, I only get the heart rate every so often rather than, you know, every second, which is

00:13:19 ◼   ► the default. Um, and those kinds of operations are things that you just have to choose because

00:13:23 ◼   ► otherwise that floor is fixed and there's nothing you can do about it in the sense of, you know,

00:13:29 ◼   ► in your case, it's like playing the sound at full volume out of the, out of the speaker.

00:13:32 ◼   ► There is a floor there that is going to be ascribed to you that you can do nothing about.

00:13:37 ◼   ► It doesn't mean there aren't things we can do to still be helpful. And I think that's

00:13:40 ◼   ► the interesting aspect of a lot of this is it's finding the places where there are these pain

00:13:46 ◼   ► points. And particularly it's finding them, yeah, finding the things that will get run,

00:13:49 ◼   ► sort of run away from you. As I think something that very often seemed to be a pattern for what I

00:13:53 ◼   ► was finding, um, in my work and like actually ran into a specific example of what you were,

00:13:57 ◼   ► you were just describing where I had a thing that was loading, you know, loads map tiles.

00:14:02 ◼   ► And typically when the app is set up such that you would download your map tiles ahead of time

00:14:07 ◼   ► so that you have them sort of offline. Um, but if you don't do that and then you go off into the

00:14:12 ◼   ► wilderness, what I would, I discovered is that, um, as soon as you lose connectivity and it tries to

00:14:17 ◼   ► load every time SwiftUI updates the map, it will try load again and try load again and try load again.

00:14:23 ◼   ► And obviously like at some point the system is intelligent about that in terms of if it,

00:14:28 ◼   ► you know, if the, if it has no internet connection, I suspect that those are failing

00:14:33 ◼   ► instantaneously. So it's not like this terrible loop, but it's still a bad loop. And it's in this

00:14:38 ◼   ► exact situation where the user does not want their battery to be running down. And so it's like,

00:14:43 ◼   ► that was something I have to resolve and have to deal with. Um, cause you have to find these situations

00:14:48 ◼   ► where you're going to use lots of battery. And I mean, the reality with this, that is feel,

00:14:52 ◼   ► it feels very like scientific method, but it's this very interesting process you have to do of

00:14:57 ◼   ► designing experiments to isolate particular variables and then running actual like real

00:15:04 ◼   ► world tests. Because there's something about battery testing that is frustrating is that very,

00:15:09 ◼   ► you know, to, to understand your battery consumption over eight hours, you have to do the thing for

00:15:15 ◼   ► eight hours. Um, and this is a situation where I very much envy Overcast being able to just play audio

00:15:21 ◼   ► rather than if you want to test what it's like to track the GPS coordinates of an Apple watch moving

00:15:27 ◼   ► through space, you kind of have to actually move the Apple watch through space for eight hours, which

00:15:32 ◼   ► is, is fine. If you know, you're like me and I'm, I'm training for a long event. And so I very often

00:15:37 ◼   ► have the, you know, the exam, the opportunity to do that, but it is going to be really frustrating

00:15:42 ◼   ► when you're supposed to be going out for like an, you know, an eight hour hike and, you know,

00:15:47 ◼   ► an hour into it, you realize this is a bad build, like something's wrong, something, you know,

00:15:50 ◼   ► something you did isn't right. And just like, well, I guess this test didn't work. And I'm just,

00:15:54 ◼   ► you know, I'm just going to have to try again the next time I go for a long hike. Um, cause you just

00:15:58 ◼   ► have to design these experiments and try things out and be, you know, be experimental, be creative

00:16:03 ◼   ► with it is something too. I think like you were saying is it isn't always going to be the thing that

00:16:07 ◼   ► you think. And so to some degree, you have to isolate different variables, experiment and test

00:16:13 ◼   ► them separately, and then make sure that you're trying to be holistic in that approach of understanding

00:16:18 ◼   ► that it isn't necessarily the obvious thing that is going to be the most power consumptive.

00:16:22 ◼   ► Sometimes it's going to be other things. And so, you know, you'll turn things off, um, incrementally

00:16:28 ◼   ► or, or experimentally and try and isolate like this variable seems to be where things are, you know,

00:16:34 ◼   ► where things are getting stuck or where there's extra power consumption, where maybe there doesn't

00:16:38 ◼   ► need to be, or if it's above what you, you know, what, what it seems to be. And so that's kind of

00:16:43 ◼   ► what we end up having to do, or at least as far as I can tell, that's what you're going to do. And

00:16:47 ◼   ► there's no easy way around it because you can, in order to really know the real life results,

00:16:52 ◼   ► you have to actually go out into the real world. Like I love the simulator for testing my core location

00:16:57 ◼   ► stuff. And I've all, you know, this, there's, we've talked about SimGenie before, which is a great tool

00:17:01 ◼   ► for being able to, you know, reproduce GPS tracks in the simulator. So you can actually test your like

00:17:08 ◼   ► logic for that. And that's useful to some degree in terms of I've done a lot of work, you know,

00:17:12 ◼   ► that improves my battery life by making my algorithms more efficient, which I can do in

00:17:16 ◼   ► the simulator. But ultimately at some point you're going to have to lace up your shoes, get out and

00:17:21 ◼   ► actually test it in the field or try it in the situations where it's going to be used. Because if

00:17:25 ◼   ► you don't, you won't actually know what the battery life will be used in practice.

00:17:29 ◼   ► Yeah, exactly. And that's, that's the answer to so many of these things. Like a lot of times it just

00:17:34 ◼   ► depends because battery life, you know, with, with the big users of it, like the screen brightness,

00:17:39 ◼   ► the speaker, you know, the usage of GPS, like those are, those are big users of it. Those it's kind of

00:17:48 ◼   ► obvious when, you know, like, okay, using the radios is power inefficient. Well, if you can like use them

00:17:56 ◼   ► less frequently, maybe batch your requests, they don't have to like constantly wake up, you know,

00:18:00 ◼   ► connect to whatever, and then go back to sleep. Like that, that, that's kind of more obvious.

00:18:04 ◼   ► Sometimes when you're dealing with optimization of processor usage or, you know, like load on the

00:18:11 ◼   ► processor, sometimes it's less obvious what will matter and what won't because the processors are

00:18:18 ◼   ► really complicated. And this is partially true of the radios too. The radios are also very complicated,

00:18:23 ◼   ► but the processors, I think more than anything, this is where you have to often just try stuff and you

00:18:29 ◼   ► can't rely on the little meter and Xcode that says power use, you know, power impact low, you know,

00:18:34 ◼   ► like that's, that's a very coarse mechanic because the reality is the processors, oftentimes they're

00:18:41 ◼   ► doing such complicated things. They're, they're managing their power. So in such a complex way,

00:18:46 ◼   ► they're, they're splitting tasks between the efficiency cores and the performance cores, you know,

00:18:51 ◼   ► they're, they're ramping up the clock speed and then ramping it back down, like, you know,

00:18:55 ◼   ► many times per second, like, you know, like they're, they're doing these things that sometimes

00:18:59 ◼   ► what you think will be inefficient or efficient won't be. Um, because sometimes they can, you know,

00:19:06 ◼   ► like for instance, if you have a certain amount of computation to, to do, and it doesn't really

00:19:11 ◼   ► matter when you do it, you might think, let me do a little bit at a time. So the CPU is only like,

00:19:15 ◼   ► you know, 5% used for a long time. Well, that actually might be less efficient than using a hundred

00:19:23 ◼   ► percent of a core for five seconds and then stopping or whatever, because that can actually

00:19:28 ◼   ► like the, some core might have to stay awake longer than it would if it's doing a long running small

00:19:35 ◼   ► task, as opposed to being able to do a big burst of work and then go to sleep for a longer time after

00:19:41 ◼   ► that. Um, the, this, this, um, pattern is called race to sleep. And the idea is oftentimes it is more

00:19:47 ◼   ► efficient with modern, uh, processors often is more efficient to just do the work really fast

00:19:53 ◼   ► at maximum power and then stop and then, you know, sleep for as long as you possibly can before you

00:19:58 ◼   ► ask it to do more. Um, and sometimes the opposite is true depending on whether that task, you know,

00:20:04 ◼   ► can run on an efficiency core or not. So, you know, as you were saying, Dave, like there is really no

00:20:08 ◼   ► better answer than you got to just test this stuff and be, you know, be willing to experiment.

00:20:13 ◼   ► And again, to many apps, this won't even be necessary to many apps. You know, if people are just

00:20:19 ◼   ► launching it briefly, no problem, like do whatever you want. But once you have

00:20:22 ◼   ► something long running, if it's some kind of, you know, background thing or, or, you know, long

00:20:27 ◼   ► foreground usage, this is going to start to matter a lot. And people, people are going to notice like,

00:20:33 ◼   ► Hey, does my phone get hot while I use this app? Or does my battery sync dramatically? Like that,

00:20:38 ◼   ► that does matter to people a lot.

00:20:40 ◼   ► Yeah. And if, and if you'll allow me a brief rant, I'm very frustrated by how the tooling we have

00:20:48 ◼   ► for this is because ultimately, like I said, we have to just do these tests. And I feel like it is,

00:20:53 ◼   ► it feels very frustrating in like whatever the 18th year of iOS's existence. That's so often I'm falling

00:21:00 ◼   ► back to like in the console, logging the battery percent as reported by the system as the best tool

00:21:07 ◼   ► I have for a lot of these things. And as a side rant, it is very frustrating that debug builds,

00:21:13 ◼   ► you know, I'm clearly a developer doing this thing. We'll still have the masked battery percentage

00:21:19 ◼   ► reported to it, which is like, where it like rounds to the nearest 5%.

00:21:22 ◼   ► Oh yeah.

00:21:23 ◼   ► Which is like, why are you doing that to me? Like that, that's, that's unnecessary. I understand it

00:21:27 ◼   ► makes sense in, you know, for fingerprinting reasons and things in like production apps, but come on,

00:21:31 ◼   ► I wish that would just give me the actual number so that I don't need to run things for like twice as long

00:21:36 ◼   ► to make sure that I'm averaging out the weird sort of rounding issues and errors there. But

00:21:41 ◼   ► nevertheless, it's something that I was just really surprised by when I went and wanted to do

00:21:45 ◼   ► like power analysis and these kinds of things. Like I expected there to be like a really detailed

00:21:50 ◼   ► instrument in Xcode that would give me a lot of the detail that, that I might want. And as far as I

00:21:56 ◼   ► could tell, there's some very basic things and some of them have sort of come and gone over the years.

00:22:01 ◼   ► Some, like sometimes you, I find these articles about tools which don't seem to exist in Xcode

00:22:05 ◼   ► anymore. But like, ultimately I kind of get a lot of t-shirt sizing with the power consumption

00:22:10 ◼   ► is the best you can do where it's like, you're doing small, medium, or large amounts of battery

00:22:16 ◼   ► use right now, which is like, okay, but if I'm trying to optimize things more specifically, it'd be

00:22:22 ◼   ► really helpful if there was some amount of more like, you're using so many, whatever, like, you know,

00:22:27 ◼   ► milliwatt hours or milliwatts per hour, whatever, like some measurement that I could actually be basing

00:22:32 ◼   ► something on or things like that. And I understand obviously measurement always has overhead. And so

00:22:38 ◼   ► that's, maybe that's why some of these things don't, aren't in there, but like in a lot of circumstances,

00:22:42 ◼   ► I wish I could take on that overhead and understand obviously it's doing a lot of extra work. So the percent,

00:22:47 ◼   ► you know, the battery percent would no longer be representative, but the measurement of what my app

00:22:52 ◼   ► was doing or what the overall system power draw is could be consistent between runs or those kinds of things.

00:22:58 ◼   ► And it was just a very, it was something that really surprised me where I feel like a lot of like instruments is

00:23:03 ◼   ► amazing and continues to get better every year, it seems, but power when battery life particularly just didn't seem like

00:23:10 ◼   ► something that there was nearly as much detail and ability for us to dig into. And particularly if you're doing

00:23:17 ◼   ► anything with watchOS, like it was shocking to me how challenging it was to, because even some of these like t-shirt sized

00:23:25 ◼   ► power usage things don't seem to apply on watchOS. And so on what I ended up doing for a bunch of my apps, like I was

00:23:31 ◼   ► saying, I was like combining, stripping these things down to their smallest parts. And sometimes I would just run the

00:23:37 ◼   ► library that I had written on my iPhone and see how it works there where I could actually get some bit more data there and run and have a

00:23:44 ◼   ► slightly faster sort of testing cycle there. And obviously the iPhone is not an Apple Watch, but it is

00:23:50 ◼   ► close and, you know, things that are bad on the iPhone are likely also going to be bad on watchOS. And so I was able to

00:23:56 ◼   ► catch some issues that way. But it was just one of these things that I was very surprised by. And maybe it is to your

00:24:00 ◼   ► point that a lot of, there's certain kinds of apps that just don't need to worry about power consumption

00:24:07 ◼   ► dramatically that, I mean, in a way that like Widgetsmith, you know, is an app that I don't think I've ever really

00:24:11 ◼   ► paid much attention to its battery consumption. Because it's an app that users tend to open,

00:24:17 ◼   ► do an operation for a short period of time, and then close the app, and that's it. And so it's very

00:24:23 ◼   ► unlikely Widgetsmith's ever going to show up, you know, in a very heavy, heavy way in a user's

00:24:27 ◼   ► battery meter. But in the places that I do use it, boy, do I wish there was some kind of way that I could

00:24:33 ◼   ► have a better insight into it. I mean, it reminds me of those things you'll see in like when you're playing,

00:24:37 ◼   ► you know, people are playing video games, and they have like a little HUD that has the current,

00:24:40 ◼   ► you know, frames per second and details about the rendering. It's like, boy, do I wish I could just

00:24:45 ◼   ► have a little HUD on the top of the screen that was telling me the current pain of power consumption as

00:24:48 ◼   ► it's being drawn from the battery or something. Like that would have made my life so much easier and

00:24:52 ◼   ► saved me so much time in this process.

00:24:54 ◼   ► You know what you should do? You should scale it up to be able to run on a Mac Mini,

00:24:57 ◼   ► spin up like, you know, a hundred of those processes and just put a kilowatt meter between

00:25:01 ◼   ► the Mac Mini and the wall, and you can see how much power it's pulling.

00:25:05 ◼   ► Just take the battery completely out of this, out of the loop, and just do it purely by the amount

00:25:11 ◼   ► of power draw that is happening on the computer. There you go. Problem solved. I don't know why I

00:25:15 ◼   ► didn't think of that.

00:25:18 ◼   ► One other thing I wanted to mention is programmatically adapting to low power mode. So this

00:25:24 ◼   ► is one thing you can do on the process info object. There's an is low power mode enabled property,

00:25:29 ◼   ► and there's some notifications there when it changes to if you want to monitor it that way.

00:25:32 ◼   ► This is one of those things that I thought was a great idea. And so I tried it. And it turns out,

00:25:40 ◼   ► so my thinking was, how about when the device is in low power mode for overcast, maybe I do things

00:25:47 ◼   ► like, you know, reduce the frame rate of animations that I'm generating manually, like those waveform

00:25:52 ◼   ► animations I had, like in the pause button. Maybe I reduce the frame rate of that. Maybe, you know,

00:25:57 ◼   ► more importantly, maybe I will reduce the frequency at which I sync back to the server. Or maybe I would

00:26:04 ◼   ► defer tasks like downloading, you know, like checking for artwork changes for podcasts and downloading new

00:26:09 ◼   ► artwork. Maybe I, you know, defer those until it's not in low power mode. And that was a great,

00:26:13 ◼   ► those were all great ideas. And they all failed. Except for the animation frame or anything. I think

00:26:18 ◼   ► I actually kept that one. But everything else I had to abandon, because the reality is many users out

00:26:26 ◼   ► there basically use low power mode all the time. It's a very, very common usage pattern that people just

00:26:33 ◼   ► like every day they just pick up their phone and flip on low power mode. And so you can't, you shouldn't

00:26:40 ◼   ► change anything in low power mode that would negatively affect your app if that was always the condition under

00:26:47 ◼   ► which it was running. So for instance, I was like, I was deferring artwork updates when I, this was years

00:26:52 ◼   ► ago now. But you know, I had this idea, I'll defer artwork updates. And I was getting complaints from

00:26:57 ◼   ► people saying, I like, but I have the wrong art for this podcast. And I like, I would have, I would

00:27:03 ◼   ► occasionally begin with some of them. And oftentimes it was, I would get to this question, and they were

00:27:07 ◼   ► actually running low power mode all the time. And so it was just never having a chance to update.

00:27:11 ◼   ► And so this is something that you can, you can do, and you know, you can make minor tweaks to what your

00:27:17 ◼   ► app is doing in response to low power mode. But I would not recommend making major tweaks. Because

00:27:23 ◼   ► and even if you tell the user, maybe if you have a banner up saying, you know, sync deferred because

00:27:27 ◼   ► of low power mode or whatever, like, that's not going to solve your problem. Because that's not going to

00:27:30 ◼   ► make people, you know, change their power using their phone. That's just going to make them, you know,

00:27:34 ◼   ► not use your app or complain about it. So be careful what you change in response to that. And make sure

00:27:41 ◼   ► it's something that the ramifications aren't too bad if you are never running in regular mode.

00:27:47 ◼   ► Yeah, and I think, so I ran into a similar sort of pattern then in the end of this update I'm

00:27:52 ◼   ► working on, where I was thinking, oh, if the user's in low power mode on their watch, like I should

00:27:57 ◼   ► do different things. And I think what I ended up settling on is that for the same reasons you're

00:28:01 ◼   ► describing, I think it would be better. And this is sort of where I'm going is there's a mode inside of

00:28:06 ◼   ► the app that does different things. And is the sort of the expedition mode,

00:28:11 ◼   ► the long run, you know, long, long walk kind of mode that the user is specifically opting into,

00:28:18 ◼   ► rather than responding to the system flag, which can be on for a variety of reasons.

00:28:22 ◼   ► It's the something that the user is saying, hey, I want to maximize my battery life,

00:28:29 ◼   ► I want to turn this on. And they're making a positive choice to do that, rather than assuming

00:28:34 ◼   ► that the reason they have low power mode on is because they want those low power features. They

00:28:39 ◼   ► may want all of the capability, but, you know, just are turning that on out of habit or out of sort of

00:28:46 ◼   ► other, other reasons or other needs. And so, or similar, like I think of in watchOS, there's some

00:28:50 ◼   ► switch, you know, some switches that you have to go and turn on if you want to enhance the battery life

00:28:55 ◼   ► in low power mode. Like it takes, can take fewer GPS readings or heart rate readings in the main

00:29:01 ◼   ► workouts app, but you have to go and turn that on rather than the system just assuming, oh, you're in

00:29:05 ◼   ► low power mode. I'm going to do that for you because you just don't want to make assumptions. And you

00:29:09 ◼   ► don't ultimately in all of this battery life is a tension between user experience and capability

00:29:14 ◼   ► and power. And like, you just, there's a certain trade-off that you have to make there and be careful

00:29:19 ◼   ► about making assumptions about that is exactly right. Like you don't want to assume that the situation

00:29:23 ◼   ► is any one state, whether that's low power mode here, whether that's, you know, network

00:29:29 ◼   ► connectivity, whether it's screen brightness, volume on the speaker, all of these things are just these

00:29:33 ◼   ► variables we're trying to balance between. And if we can get the balance right, we can improve the overall

00:29:38 ◼   ► battery, you know, user experience by giving a user more time with our app, which is ultimately

00:29:43 ◼   ► wonderful, but we just have to be thoughtful and careful, you know, to arrive at that place in a way that

00:29:47 ◼   ► makes everybody happy.

00:29:48 ◼   ► Thanks for listening, everybody. And we'll talk to you in two weeks.

00:29:52 ◼   ► Bye.