PodSearch

Under the Radar

81: Profiling

 

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

00:00:04 ◼   ► I'm Marco Armet.

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

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

00:00:11 ◼   ► So as a follow-up in some ways to what we were talking about last week with debugging,

00:00:14 ◼   ► it seemed only right to this week talk about profiling and to talk about sort of that next

00:00:20 ◼   ► step beyond just making your app work correctly, which is largely what debugging is focused

00:00:25 ◼   ► on, and instead to make it work in a performant way, to work not just correctly, but to work

00:00:34 ◼   ► well as well.

00:00:35 ◼   ► And there are some parts of profiling that are also kind of debugging and digging out

00:00:41 ◼   ► kind of more subtle bugs, but a lot of what I've—when I turn to profiling, you know,

00:00:45 ◼   ► when I'm in Xcode, you know, I can run, I can build and run, I can build and test,

00:00:50 ◼   ► build and profile, build and analyze.

00:00:51 ◼   ► Like, those are kind of the core things before I archive the build and send it off to iTunes

00:00:56 ◼   ► Connect.

00:00:57 ◼   ► And profiling tends to come towards the end of the process.

00:01:00 ◼   ► And profiling generally in, you know, in this context is running Xcode, running your build

00:01:06 ◼   ► while attached to instruments on your Mac, where instruments is this tremendously powerful

00:01:13 ◼   ► tool that does way more things than I could possibly really understand.

00:01:18 ◼   ► But the things that I do understand it does is just amazing, because it can give you insight

00:01:22 ◼   ► into what is happening inside your application in a way that you can't really measure any

00:01:28 ◼   ► other way, because it's kind of doing this—it's this interesting combination of measuring

00:01:32 ◼   ► external things about your app, but it's doing it in a context where it is aware of

00:01:38 ◼   ► your source code and aware of your app in a way that can give you great insight into

00:01:43 ◼   ► what's going on.

00:01:45 ◼   ► And there's a whole bunch of areas that we'll dive into from where profiling is

00:01:49 ◼   ► really useful.

00:01:50 ◼   ► But I will also mention that the one thing I always do before I go into profiling—you

00:01:54 ◼   ► know what I mean—at the point in building an app where I hit the point where I feel

00:01:59 ◼   ► like now I need to start tuning things down, which is largely what profiling gets into.

00:02:04 ◼   ► Like, just earlier today, I was dealing with something with big data import, and I got

00:02:08 ◼   ► it working correctly, but the import was taking about a minute.

00:02:11 ◼   ► And I was like, "Mm, let me see if I can make this faster."

00:02:14 ◼   ► And so that's when I turned to the profiler, and I work to make it faster.

00:02:19 ◼   ► I want to make no changes to its functionality, I just want to make it faster.

00:02:22 ◼   ► But the first thing I always do is I also, before I go into profiling, I always run build

00:02:26 ◼   ► and analyze.

00:02:27 ◼   ► And build and analyze in Xcode is a tool that—it's static analysis of your application.

00:02:33 ◼   ► So it's looking for kind of structural problems or issues that you may not be aware of, like

00:02:40 ◼   ► things where you're assigning to a value and never reading from it, or wasted work

00:02:45 ◼   ► or structural problems.

00:02:46 ◼   ► And I will say, it catches fewer things now than it used to for me, because I think a

00:02:51 ◼   ► lot of this has been rolled into the compiler itself.

00:02:54 ◼   ► And so as I'm typing out these issues, they're being lit up inside of my source editor.

00:03:01 ◼   ► But it's still, every now and then, it will catch something that is one of these things

00:03:05 ◼   ► that saves me a whole bunch of effort in the profiling phase, just by saying, "Hey, you're

00:03:11 ◼   ► doing all this work and then throwing the value away without ever reading from it.

00:03:15 ◼   ► Do you actually mean to do that?"

00:03:17 ◼   ► So for me, I always run build and analyze first, but then I dive into the profiler.

00:03:22 ◼   ► And that's kind of the flow that I find to work pretty well.

00:03:25 ◼   ► Yeah, I mean, there's this whole discussion about whether you should even be optimizing

00:03:31 ◼   ► things before it's really a problem.

00:03:33 ◼   ► The concept of premature optimization.

00:03:36 ◼   ► And I feel like there's, as with most things, there's a balance to be struck.

00:03:40 ◼   ► I should have a bell for every time I say that.

00:03:43 ◼   ► But there's a balance to be struck here.

00:03:45 ◼   ► And the way you did it, in the example you decided was great, which is you didn't actually

00:03:51 ◼   ► go looking for deep profiling information until there was something about your app that

00:03:56 ◼   ► was noticeably slow.

00:03:58 ◼   ► And that's when you decided, "Okay, I need to investigate this.

00:04:00 ◼   ► I need to find this problem and fix it."

00:04:02 ◼   ► That is a very healthy way to do things, as opposed to trying to micro-optimize every

00:04:10 ◼   ► little possible step along the way, because usually if you try to do that, your code becomes

00:04:15 ◼   ► less readable, less obvious, usually more bug-prone.

00:04:19 ◼   ► And it's also just wasted effort a lot of the time.

00:04:21 ◼   ► If you're going to go through and micro-optimize something, that ends up being such a tiny

00:04:26 ◼   ► fraction of usage time that it's not even really worth having optimized.

00:04:32 ◼   ► And so step one is try to avoid premature optimization.

00:04:36 ◼   ► And it's arguable what counts as premature or unnecessary.

00:04:41 ◼   ► But for the most part, if something is going to take a lot of work to make really fast,

00:04:48 ◼   ► it's a good thing to first consider how necessary is this, and then to use the profiler to first

00:04:56 ◼   ► profile it beforehand and see how fast or slow it is without any optimization that you

00:05:01 ◼   ► custom do.

00:05:02 ◼   ► And then as you try optimization methods, profile it and see, is this really helping?

00:05:08 ◼   ► Because if it isn't, roll it back.

00:05:10 ◼   ► Or sometimes you might think you're making something faster, or you might even be making

00:05:13 ◼   ► it slower.

00:05:14 ◼   ► And so you always have to not necessarily-- if you're a programmer, I feel like there's

00:05:19 ◼   ► this instinct to make things what you think might be fast and clever and efficient and

00:05:26 ◼   ► whatever else.

00:05:27 ◼   ► But a lot of times, modern hardware is complicated.

00:05:30 ◼   ► And a lot of times, things are not what you think they are in terms of relative performance.

00:05:35 ◼   ► You might think that the more naive approach is super slow, and your clever possible optimization

00:05:42 ◼   ► is super fast.

00:05:44 ◼   ► But if you actually measure it with the profiler, you might find the opposite.

00:05:47 ◼   ► You might find that, oh, it turns out the naive approach is being optimized by the compiler

00:05:52 ◼   ► or hardware in a way that ends up making it faster than your custom optimization might

00:05:58 ◼   ► be, or at least not substantially slower.

00:06:02 ◼   ► There's been all sorts of optimizations over time to things like the Objective-C runtime

00:06:07 ◼   ► and the compiler and the tools.

00:06:10 ◼   ► And the hardware is so good now that a lot of things might seem like good candidates

00:06:15 ◼   ► for optimization, but they actually aren't.

00:06:18 ◼   ► And only the profiler running only on the device hardware that you're targeting can

00:06:24 ◼   ► really tell you that a lot of the time.

00:06:26 ◼   ► And I think, too, it's also a good point along those same lines of the importance of

00:06:30 ◼   ► doing profiling in a quantitative approach, which is probably no surprise that that's

00:06:35 ◼   ► what I love about profiling.

00:06:36 ◼   ► Wow, I'm so surprised.

00:06:38 ◼   ► But I love that you can-- and I think it's important to look at this thing from a sense

00:06:43 ◼   ► of this operation is starting off taking this amount of time.

00:06:48 ◼   ► Or depending on which part of the profiler you're working in, it'll be measured in

00:06:52 ◼   ► seconds or frames per second or whatever it is.

00:06:55 ◼   ► And having a number that you're trying to move, to affect.

00:07:01 ◼   ► And be mindful about are you able to make substantial changes to that number.

00:07:07 ◼   ► So in this case that I was working on this morning, I have an import that's taking

00:07:11 ◼   ► a minute to run.

00:07:12 ◼   ► So 60 seconds is my baseline.

00:07:14 ◼   ► And how can I affect change to that?

00:07:18 ◼   ► And the trap that I used to fall into a lot with profiling is feeling like I was going

00:07:25 ◼   ► to be making progress as I was making these little improvements to that.

00:07:29 ◼   ► Going from my 60 second target to 57 seconds by introducing some crazy convoluted scheme.

00:07:35 ◼   ► And in theory, if you keep making these lots of small chunks into it, in theory you'll

00:07:42 ◼   ► end up better.

00:07:43 ◼   ► But in general, I think the thing that I've found more often is that my app is just worse

00:07:48 ◼   ► as a result.

00:07:51 ◼   ► When profiling works well, I'll start off with a big number, I'll find a bottleneck,

00:07:56 ◼   ► I'll find some issue that if I can alleviate, we'll take that number and drop it in half.

00:08:02 ◼   ► Or even better maybe.

00:08:04 ◼   ► And if I can't find an optimization that will drop it in these big orders of magnitude

00:08:11 ◼   ► changes, usually I just say, "That's as good as it's going to be."

00:08:14 ◼   ► And I avoid the feeling of chasing down all these little micro-optimizations, because

00:08:21 ◼   ► almost always they're going to reduce code readability, testability, understandability

00:08:26 ◼   ► in the future.

00:08:27 ◼   ► It's usually going to be something that I will regret and my future self will be very

00:08:31 ◼   ► mad at my current self for doing.

00:08:34 ◼   ► And it's just so much more bug prone too.

00:08:36 ◼   ► I always have that bite me.

00:08:38 ◼   ► Whenever I do any kind of clever optimization, it always introduces bugs that I didn't anticipate.

00:08:44 ◼   ► And I'm working around those bugs forever from that point forward until I get rid of

00:08:49 ◼   ► the optimization.

00:08:50 ◼   ► Yeah.

00:08:51 ◼   ► And so it's vitally important to make sure that if this optimization you're doing has

00:08:55 ◼   ► a measurable and dramatic impact, like half the time, a tenth of the time, whatever it

00:09:01 ◼   ► is, then okay, maybe this trade-off is worth doing.

00:09:04 ◼   ► But if you aren't measuring it, you'll have no way to know the magnitude of that impact.

00:09:10 ◼   ► Because often I'll go down there in profile, I'll be like, "Ah, I don't think I can

00:09:14 ◼   ► make this any better."

00:09:15 ◼   ► And that's it.

00:09:16 ◼   ► And sometimes things are just slow in apps and that's okay.

00:09:19 ◼   ► It's better for it to work correctly and be slow than to work fast and break because

00:09:24 ◼   ► that's not really working at all.

00:09:27 ◼   ► Exactly.

00:09:28 ◼   ► And usually, I like what you said a minute ago, usually the correct number of optimizations

00:09:34 ◼   ► to do to fix a certain problem is usually between zero and one.

00:09:39 ◼   ► Because if, as you said, if you run a time profiler in instruments and you do the thing

00:09:46 ◼   ► in your app that you think is slow, if there's not one big thing there that's taking up

00:09:52 ◼   ► most of the time, it's probably not even worth doing optimization this way.

00:09:57 ◼   ► It's probably instead, if this is a problem for your app, it's probably instead worth

00:10:00 ◼   ► thinking like, "Okay, how can I either avoid doing this at all or how can I do it in a

00:10:05 ◼   ► different way where it wouldn't be a problem?"

00:10:08 ◼   ► And if you still have to do some kind of massive CPU intensive work, which I think very few

00:10:13 ◼   ► apps do, then you look into things like, "Okay, well let me do this on a background thread

00:10:18 ◼   ► and provide a progress UI to the user so that at least, if there's no way to make this

00:10:24 ◼   ► fast, at least make it nice during use and make it clear what's going on."

00:10:29 ◼   ► That's when you get into that kind of thing.

00:10:30 ◼   ► But usually, that's not what we're dealing with in our apps.

00:10:33 ◼   ► Usually we're dealing with more simple things.

00:10:36 ◼   ► One example that I ran into is that in Overcast, there's this collection of podcasts and

00:10:43 ◼   ► episodes and everything.

00:10:44 ◼   ► And there's a lot of parts of the app that have to reload their data sources or update

00:10:50 ◼   ► their data sources whenever the list of playable podcast episodes changes.

00:10:57 ◼   ► This is like whenever a new episode comes in or if the user deletes or completes an

00:11:01 ◼   ► episode or when a download completes in certain contexts where things can only be downloaded.

00:11:07 ◼   ► So there's a few conditions here where whenever these things change, all these different parts

00:11:14 ◼   ► of the app need to update themselves on the list of playable items for whatever reason

00:11:19 ◼   ► that they need that list.

00:11:22 ◼   ► This was a very, very heavy operation whenever this would happen because so many parts of

00:11:27 ◼   ► the app need that.

00:11:28 ◼   ► This is like the long shortcuts, the playable content manager for CarPlay, the playlist

00:11:32 ◼   ► screen, the list of podcasts within each playlist.

00:11:36 ◼   ► If any of these things are open and some of them are always running, like the CarPlay

00:11:38 ◼   ► manager, you need to know when that changes.

00:11:42 ◼   ► So whenever the playable content notification was fired, huge amounts of work had to be

00:11:48 ◼   ► done in the app.

00:11:49 ◼   ► This can be done in lots of apps like whenever you have a table view, reload data.

00:11:53 ◼   ► This is a very common thing.

00:11:56 ◼   ► Something in the data source changed, reload data.

00:11:58 ◼   ► That's easiest most of the time than trying to do anything dynamic.

00:12:03 ◼   ► And so it's a pretty common pattern.

00:12:05 ◼   ► And what I was finding was that it was kind of behaving slowly.

00:12:09 ◼   ► The app was kind of behaving slowly and people were complaining on certain phones, like the

00:12:12 ◼   ► older ones, like the iPhone 5 or whatever else.

00:12:14 ◼   ► So I loaded it up and I noticed on this old hardware, yeah, this is really slow.

00:12:19 ◼   ► So I profiled it and saw it was all these table view reloads and everything from the

00:12:23 ◼   ► playable content manager being updated.

00:12:26 ◼   ► And so the solution here was just make that update less often.

00:12:30 ◼   ► I was having an update on every change to the relevant tables in the database, like

00:12:37 ◼   ► the episode table.

00:12:38 ◼   ► Every time an episode was updated, refresh the playable content.

00:12:43 ◼   ► But that's things like when the user listens to a few more seconds of the episode and it

00:12:47 ◼   ► saves the progress to disk on how far they've listened.

00:12:50 ◼   ► Well, I don't need to update it for that.

00:12:52 ◼   ► It doesn't matter whether they've listened 30 seconds or 35 seconds in.

00:12:55 ◼   ► So I added optimizations for things like, okay, well, don't even fire the playable content

00:13:00 ◼   ► change notification unless certain fields have changed that actually matter.

00:13:06 ◼   ► And I built an architecture in place for like whenever anything is listening for database

00:13:10 ◼   ► changes in my FC model database layer class, which is open source if you want to use it,

00:13:14 ◼   ► although I wouldn't recommend it, but if you do want to use it, go ahead.

00:13:19 ◼   ► There's now things in there where like you can say like notify me if only these columns

00:13:24 ◼   ► of this table change.

00:13:26 ◼   ► And then so like I was able to build these optimizations that have pretty big impacts

00:13:30 ◼   ► but are more in the realm of like reducing the amount of work that takes place and reducing

00:13:36 ◼   ► the frequency of high needs operations rather than going super low level and trying to make

00:13:43 ◼   ► like table view reloads substantially faster all over the app.

00:13:46 ◼   ► Yeah, because I think then the big point there is it's like more often than not, the great

00:13:51 ◼   ► thing that I find in profiling is that like the issue is something understandable.

00:13:57 ◼   ► The optimization should likely be an obvious, tractable thing.

00:14:01 ◼   ► Like you go through the time profiler, which is probably the one that I spend the most

00:14:04 ◼   ► time using, and it's like, why am I calling this method 500 times?

00:14:08 ◼   ► Oh, that's interesting.

00:14:10 ◼   ► It's getting called 500 times a second because it's keyed into some other part of the app

00:14:15 ◼   ► that is doing something that it really doesn't need to be communicating with it.

00:14:20 ◼   ► It's like it's a big obvious change.

00:14:21 ◼   ► Like, huh, that doesn't look right.

00:14:23 ◼   ► And it's a very obvious change.

00:14:25 ◼   ► And those are the things where if you see one of those, it's like, great, you just

00:14:28 ◼   ► found like you can make a change that is very low risk.

00:14:31 ◼   ► You're not kind of, it's not like, oh, no, I need to like dive into accelerate and

00:14:35 ◼   ► do some crazy GPU version of my algorithm to avoid.

00:14:39 ◼   ► Like, if that's what you're doing, like, that is very fun.

00:14:41 ◼   ► I mean, that might be fun.

00:14:43 ◼   ► That's super interesting.

00:14:44 ◼   ► And like, see our previous episode on indulgences.

00:14:47 ◼   ► Yeah, like, that's really cool if you if you can a do that and be if that's relevant

00:14:53 ◼   ► to your application.

00:14:55 ◼   ► But in the context of something like for most applications, like that's almost certainly

00:14:59 ◼   ► not the answer.

00:15:00 ◼   ► Like the right answer is just finding the methods that is being called too many times,

00:15:04 ◼   ► you know, where it's like, it's your have a method that's called outside of an F where

00:15:07 ◼   ► it should be called inside of an F, you know, it's just like, oh, you should really only

00:15:10 ◼   ► be calling this method at the end, rather than every time you cycle through the loop

00:15:14 ◼   ► or that kind of thing.

00:15:16 ◼   ► And anytime you see one of those, you're like, perfect, like, like the profiler just

00:15:19 ◼   ► saved me because it was this thing that I wouldn't see otherwise.

00:15:23 ◼   ► Because it's hard to sometimes notice that kind of an issue.

00:15:26 ◼   ► But when the profiler says, you call this method, you know, like, 98% of the execution

00:15:31 ◼   ► time of your app is being called in this one method.

00:15:34 ◼   ► You're like, huh?

00:15:36 ◼   ► Well, that's interesting.

00:15:37 ◼   ► And it's telling you it's giving you information that you just wouldn't know any other way.

00:15:41 ◼   ► Yeah.

00:15:42 ◼   ► We are sponsored this week by Linode, fast, powerful web hosting for your projects that

00:15:47 ◼   ► you can set up in just seconds with easy to understand tools that let you choose your

00:15:51 ◼   ► resources and your Linux distribution, giving you the power and flexibility you need.

00:15:55 ◼   ► All this starting at just $5 a month.

00:15:58 ◼   ► And that includes right now Linux server with one gig of RAM in the Linode cloud.

00:16:02 ◼   ► And they're always making their deals better as hardware allows.

00:16:04 ◼   ► It's pretty awesome being a Linode customer.

00:16:06 ◼   ► I mean, we've been Linode customers for years now, and I cannot recommend them enough.

00:16:12 ◼   ► They don't, they're not paying me to say this.

00:16:13 ◼   ► They're paying me to the rest of it, but this, they cannot pay me to say.

00:16:16 ◼   ► I love Linode.

00:16:17 ◼   ► I use Linode and I recommend Linode.

00:16:19 ◼   ► Anyway, back to their script.

00:16:21 ◼   ► They have over 400,000 customers, including me and David, who are all serviced by their

00:16:24 ◼   ► friendly 24/7 support team.

00:16:27 ◼   ► You can email them, call them, or even chat over IRC.

00:16:29 ◼   ► If you need help, they're there for you.

00:16:31 ◼   ► Linode has comprehensive guides also and support documentation to teach you everything you

00:16:36 ◼   ► need to know for setting up and managing a Linux virtual server.

00:16:39 ◼   ► And their control panel is very nicely designed with a focus on ease of use and simplicity.

00:16:44 ◼   ► And believe me, I've seen a lot of web hosting panels over the years.

00:16:48 ◼   ► I've never seen one as nice as Linode.

00:16:50 ◼   ► It's not even close.

00:16:52 ◼   ► You can deploy, boot, resize, and clone nodes in just a few clicks.

00:16:57 ◼   ► They have two-factor authentication.

00:16:58 ◼   ► It is the full package for your infrastructure needs.

00:17:01 ◼   ► So they have awesome pricing options available.

00:17:04 ◼   ► You can get a server with one gig of RAM for just five bucks a month, as I said earlier.

00:17:07 ◼   ► And it scales all the way up to truly ridiculous resource levels at what I consider to be the

00:17:12 ◼   ► best values in the business.

00:17:14 ◼   ► For example, 16 gigs of RAM for just 60 bucks a month.

00:17:17 ◼   ► Across the board, they're offering twice the amount of RAM that you get elsewhere most

00:17:21 ◼   ► of the time.

00:17:22 ◼   ► So as a listener of this show, if you sign up at linode.com/radar, you'll not only be

00:17:27 ◼   ► supporting us, but you also get $20 towards any Linode plan.

00:17:30 ◼   ► And they have a seven-day money-back guarantee, so there's nothing to lose.

00:17:33 ◼   ► So check out linode.com/radar.

00:17:36 ◼   ► To learn more, sign up and take advantage of that $20 credit.

00:17:39 ◼   ► Or you can use promo code radar2017 at checkout.

00:17:43 ◼   ► Thank you so much to Linode, my favorite web host, for sponsoring this show and all of

00:17:48 ◼   ► Relay FM.

00:17:49 ◼   ► So as we wind this up, I think the place that it seems reasonable to go is to dive into

00:17:55 ◼   ► a little bit of the actual tools within instruments that we use the most.

00:18:01 ◼   ► And I think for me, the one that I use, like probably 90% of my profiling, is the activity

00:18:06 ◼   ► monitor, which is an instrument that essentially, its goal is-- I mean, I'm definitely oversimplifying

00:18:13 ◼   ► it, but essentially it counts the number of times and the amount of time spent on each

00:18:17 ◼   ► line of code in your app while the app is running.

00:18:20 ◼   ► I believe you're thinking of the time profiler.

00:18:22 ◼   ► Yes.

00:18:23 ◼   ► Does that know what I said?

00:18:24 ◼   ► You said activity monitor.

00:18:25 ◼   ► It's fine.

00:18:26 ◼   ► Sure.

00:18:27 ◼   ► Common mistake.

00:18:28 ◼   ► The time profiler.

00:18:29 ◼   ► You can run that one too.

00:18:30 ◼   ► Does the activity monitor run at the same time profiler usually?

00:18:33 ◼   ► I think so.

00:18:34 ◼   ► I usually just use the built-in Xcode meters for general activity monitoring.

00:18:38 ◼   ► Yeah.

00:18:39 ◼   ► Anyway, the time profiler is a tool that I use the most often, which counts the number

00:18:45 ◼   ► of times and the duration of the time that is spent on each line of code in your app.

00:18:49 ◼   ► And it's a tremendously powerful tool for just finding bottlenecks, because it will

00:18:52 ◼   ► tell you-- what I usually do is you kick that off and running, and then you sit there in

00:18:57 ◼   ► your app.

00:18:58 ◼   ► If it's an operation that you can do multiple times, you do it multiple times.

00:19:03 ◼   ► Or if it's a long operation, you kick that off.

00:19:06 ◼   ► And you can just get this great sense of where to go looking for the biggest impacts.

00:19:12 ◼   ► Where are the biggest bottlenecks?

00:19:14 ◼   ► And sometimes, honestly, I've even just run it-- when I'm finishing a big update, I will

00:19:18 ◼   ► just run the time profiler and just use the app generally for five minutes, and then see

00:19:26 ◼   ► where the biggest uses of code are.

00:19:29 ◼   ► And sometimes you'll just discover things that you-- it's not necessarily performance

00:19:32 ◼   ► issues, but you're like, huh, that's interesting, looking for inconsistencies or problems.

00:19:36 ◼   ► But in general, it's just a very valuable tool to get that sense of where are the slow

00:19:42 ◼   ► parts of my app, or where are the parts of the app where there's the biggest bottlenecks

00:19:46 ◼   ► or the biggest use of code that is probably worth double-checking that it's as good as

00:19:50 ◼   ► it can be.

00:19:51 ◼   ► Right.

00:19:52 ◼   ► And it might not even be your code.

00:19:53 ◼   ► It might be some of Apple's code.

00:19:55 ◼   ► But that's still useful to know, and it still might help you avoid certain unnecessary work.

00:20:00 ◼   ► And I would also say, in general, when you're running the app, use the built-in Xcode meters

00:20:07 ◼   ► in all parts of development.

00:20:09 ◼   ► Whenever you run the app, use those meters.

00:20:11 ◼   ► Just glance at it, because it'll give you an idea of what kind of CPU usage, memory

00:20:16 ◼   ► usage, energy usage-- it'll give you an idea of what's normal for your app.

00:20:21 ◼   ► That way, if you make a change, you notice that.

00:20:23 ◼   ► This is the same way why I love the Mac app iStat menus, because I can tell all the time

00:20:30 ◼   ► what my Mac's CPU usage and stuff is so I know what's normal, so I can spot easily when

00:20:35 ◼   ► something isn't normal.

00:20:36 ◼   ► And so it's similar here when making your apps.

00:20:39 ◼   ► Use the metering and the tools frequently, so that way you have a baseline knowledge

00:20:43 ◼   ► of what's OK, so when you mess something up, you'll spot it quickly.

00:20:48 ◼   ► I would also say, in instruments-- this is a little tip for me on instruments-- for some

00:20:52 ◼   ► reason, it's a three-paned interface, kind of like Xcode's three panes, but for some

00:20:58 ◼   ► reason the rightmost pane is off by default, and that makes it really hard to see the value

00:21:04 ◼   ► of things like Time Profiler.

00:21:06 ◼   ► For a long time, I could not figure this out until I saw that that pane was off and I turned

00:21:09 ◼   ► it on, and it will show you the line of code that is on where all the work is happening,

00:21:14 ◼   ► but it doesn't do that if you don't turn on the third pane, so please turn the third pane

00:21:18 ◼   ► on.

00:21:19 ◼   ► I would also say that there's also valuable tools in the simulator.

00:21:23 ◼   ► Besides the stuff in instruments, just in the iOS simulator, you can see a lot of potential

00:21:30 ◼   ► issues in Performance Bottleneck, especially in rendering, in visual rendering of things.

00:21:35 ◼   ► They have modes where they will color in the interface various tint colors or overlay colors

00:21:42 ◼   ► for things like alpha-blended layers, which are slower to render to screen than opaque

00:21:46 ◼   ► layers, things like misaligned views, where you might have a view on a 0.3 pixel boundary

00:21:51 ◼   ► instead of a 1.0 or a 0.5 pixel boundary, things like that.

00:21:56 ◼   ► They're very, very helpful in the simulator, and there's a debug menu in the simulator,

00:21:59 ◼   ► and it's all right there, color misaligned layers or whatever.

00:22:04 ◼   ► Use these tools, and even if you don't use them every single day, I don't think anybody

00:22:08 ◼   ► does, but use them maybe every major version or every couple of weeks or every couple of

00:22:14 ◼   ► months, or whenever you make a big change to the interface or to the way images are

00:22:18 ◼   ► handled or things like that, because frame rates of your app and the resource usage of

00:22:24 ◼   ► your app can be dramatically affected by how much blending it's doing or how much off-screen

00:22:28 ◼   ► rendering it's having to do.

00:22:30 ◼   ► The simulator just makes it so incredibly easy to find these things, to spot these things,

00:22:35 ◼   ► and then to verify that you fixed them.

00:22:38 ◼   ► Use these tools.

00:22:40 ◼   ► I am guilty of underusing instruments, because instruments is very complicated and can be

00:22:45 ◼   ► very intimidating, and so I really only use it to a very shallow level.

00:22:50 ◼   ► Like David, my most commonly used one by far is Time Profiler.

00:22:54 ◼   ► There's lots of other things it can do.

00:22:57 ◼   ► WBC sessions are usually pretty good about it.

00:22:59 ◼   ► If you want to learn more about it, you can look through the archive of WBC videos, because

00:23:04 ◼   ► almost every year they do one on instruments and advanced debugging and profiling and things

00:23:07 ◼   ► like that.

00:23:08 ◼   ► So I highly recommend that you check those out, because there are tools here to do pretty

00:23:14 ◼   ► remarkable things and to spot lots of possible areas for easy wins in your app.

00:23:20 ◼   ► Like we mentioned earlier, you shouldn't go through and micro-optimize everything,

00:23:22 ◼   ► but usually there's a couple of big things in an app that you can just make a small change

00:23:27 ◼   ► here or there to have a really big impact.

00:23:30 ◼   ► That's the kind of optimization that profiling is best at revealing to you, and that's what's

00:23:37 ◼   ► the best use of your time to actually work on.

00:23:41 ◼   ► And I think those are the kinds of things that...

00:23:43 ◼   ► I mean, the number of times I've gone to a WBC session and I have some kind of performance

00:23:52 ◼   ► issue, then they'll have labs where it makes sense to go and talk to somebody.

00:23:55 ◼   ► The first thing they always do is they open up instruments and they go into the core animation

00:24:01 ◼   ► instrument, which allows you to turn on all those cool blending color schemes for your

00:24:07 ◼   ► app, but on device, so they'll run on your actual iPhone.

00:24:10 ◼   ► They'll kick up the app, they'll have the time profiler running, the core animation

00:24:16 ◼   ► instrument running with all of those different color keys turned on, and they just use the

00:24:20 ◼   ► app and very quickly they can usually find things.

00:24:23 ◼   ► You very quickly see, "Huh, why is the entire app...

00:24:26 ◼   ► I can't remember what the bad color is, it's probably red."

00:24:29 ◼   ► It's like if the whole app turns red when you're scrolling your table view, it's like,

00:24:33 ◼   ► "Why are you doing that?

00:24:34 ◼   ► Why do you have all of these semi-transparent things overlaid on each other?"

00:24:38 ◼   ► You're doing all this work that you don't need to be doing.

00:24:41 ◼   ► Or in the time profiler, similarly, they can find it.

00:24:45 ◼   ► The core animation instrument is a great one too for just quantifying your graphical performance,

00:24:50 ◼   ► which is really hard to do otherwise, I think, because it'll tell you the number of frames

00:24:54 ◼   ► per second you're getting.

00:24:56 ◼   ► Ideally, your goal is to be able to do operations at 60 frames a second, which is the maximum

00:25:02 ◼   ► refresh rate of an iPhone.

00:25:03 ◼   ► So if you aren't getting that, you can scroll your table view and see what your update rate

00:25:09 ◼   ► is.

00:25:10 ◼   ► And if it's not 60, then you're like, "Okay, now I know I have something to work with,"

00:25:13 ◼   ► rather than just like, "It feels slow," or "It feels jerky."

00:25:17 ◼   ► You can have these things that aren't really quite as quantifiable.

00:25:19 ◼   ► And if it's not quantifiable, it's really hard to actually know if you're making progress

00:25:24 ◼   ► as you're fixing things.

00:25:27 ◼   ► We mentioned in passing a little while ago the Accelerate framework.

00:25:32 ◼   ► This is something that a lot of developers, I don't think, know about, and most developers

00:25:36 ◼   ► probably don't need it.

00:25:38 ◼   ► But what this is is basically a collection of pretty low-level functions to do bulk operations

00:25:46 ◼   ► on vectors, on a massive array of floating point numbers, or matrices, graphics operations,

00:25:54 ◼   ► things like that.

00:25:57 ◼   ► Most apps will never need this.

00:25:58 ◼   ► But if--

00:25:59 ◼   ► - I've never needed it.

00:26:00 ◼   ► - Right.

00:26:01 ◼   ► I only needed it when I started working with sound, because a lot of the functions of working

00:26:05 ◼   ► with sound are made very, very nice in Accelerate.

00:26:10 ◼   ► The VDSP section of it is kind of amazing for working with sound.

00:26:13 ◼   ► It's designed to do that, really.

00:26:15 ◼   ► And I would say that if your app is spending a good amount of time doing math of any sort,

00:26:23 ◼   ► doing any kind of math operations on very large numbers of values, so if you're having

00:26:28 ◼   ► to add, subtract, multiply 500 numbers at once for some reason, look into the Accelerate

00:26:36 ◼   ► framework.

00:26:37 ◼   ► It looks kind of intimidating at first.

00:26:39 ◼   ► Again, there's good WBCC sessions on it.

00:26:41 ◼   ► And once you figure out the crazy function naming scheme, it actually makes sense.

00:26:46 ◼   ► So I would strongly recommend, if you're spending a meaningful amount of time on math, on large

00:26:52 ◼   ► numbers of numbers, check out Accelerate.

00:26:55 ◼   ► It's awesome.

00:26:56 ◼   ► - Yeah, I've never had to dive into that myself, but that's just the nature of the apps that

00:26:59 ◼   ► I make.

00:27:00 ◼   ► - Yeah, I mean, again, it's one of those optimizations where you would probably never, most apps

00:27:05 ◼   ► would probably never need it, but again, it's like if you see in Time Profile, oh, this

00:27:10 ◼   ► one function has to compute the square root of 400 values.

00:27:14 ◼   ► That's actually taking a noticeable amount of time, because I'm calling it so often,

00:27:17 ◼   ► or there's so many values, and it's a processor or whatever else.

00:27:20 ◼   ► You could fix that with one line of code that might be 10 times faster.

00:27:23 ◼   ► - Yeah, and I guess the last profile that's probably worth mentioning is the allocations

00:27:29 ◼   ► and leaks and memory profiling tools that you have in Xcode.

00:27:33 ◼   ► And I mean, these have gotten incredibly sophisticated compared to what they were years ago.

00:27:39 ◼   ► I think you can now get these dynamic memory graphs showing you your retain cycles visually,

00:27:45 ◼   ► and it's gotten very clever, but any time, and this is, I think, what you were mentioning

00:27:51 ◼   ► earlier, the importance of checking your little build and debug graphs just within Xcode while

00:27:57 ◼   ► you're running, any time I see the memory footprint of my app going up over time, especially,

00:28:06 ◼   ► you'll see it jumps up and then it stabilizes and then it jumps up again.

00:28:09 ◼   ► It's like, uh-oh, something, I'm doing something and then never getting rid of that memory.

00:28:14 ◼   ► And the profiler is a tremendous tool for being able to show you what you're doing wrong.

00:28:19 ◼   ► It's like, here you're creating lots of objects and then keeping a reference to them somewhere

00:28:26 ◼   ► that you shouldn't be or something like that.

00:28:28 ◼   ► Usually it's, you kind of get the sense of the different shapes of your memory structure

00:28:35 ◼   ► and you get a sense for when it's a problem and when it's not.

00:28:37 ◼   ► 'Cause sometimes you do need to use more memory and that's fine, but if you have, you see

00:28:42 ◼   ► this constantly growing or this stepwise function that just keeps, never comes back down to

00:28:48 ◼   ► a stable state, it's probably time to open the allocations or the leaks tool and dig

00:28:53 ◼   ► around and see what's wrong.

00:28:55 ◼   ► - Yeah, and all of this also, the importance of all of this grows as the amount of time

00:29:01 ◼   ► people tend to use your app goes up.

00:29:04 ◼   ► It's really important for me, for a podcast player, 'cause that can be running in the

00:29:07 ◼   ► background for hours, so it really has to be stable and performance and memory have

00:29:11 ◼   ► to be stable.

00:29:12 ◼   ► But if you're making a utility app that somebody opens up once to convert a unit and then closes

00:29:16 ◼   ► and won't use again for three days, it's less important and you can spend this time on things

00:29:22 ◼   ► that are better for your business rather than micro-optimizing everything.

00:29:26 ◼   ► Anyway, we are out of time this week, so thank you very much for listening and we'll be back

00:29:30 ◼   ► next week with our WWDC wish list, predictions, whatever it is, whatever makes sense, we'll

00:29:34 ◼   ► do that next week.

00:29:35 ◼   ► So thanks everybody and we'll talk to you then.

00:29:37 ◼   ► - Bye.

00:29:38 ◼   ► [BLANK_AUDIO]