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]