Podcast Search

Developing Perspective

#117: Avoid, Defer, Remember.

Select a time to play from there. The line being spoken is highlighted as the audio plays.

0:00:00Hello and welcome to Developing Perspective. Developing Perspective is a podcast discussing

0:00:04news of note and iOS development, Apple and the like. I'm your host, David Smith. I'm

0:00:08an independent iOS and Mac developer based in Herne, Virginia. This is show number 117

0:00:13and today is Tuesday, April 2nd, 2013. Developing Perspective is never longer than 15 minutes,

0:00:18so let's get going.

0:00:19All right. So first, an explanation of why I was on the show last week. I was doing a

0:00:23whole lot of different family stuff, Easter related, getting out of the household, it

0:00:27It was painted, all kinds of things,

0:00:28and it just didn't work to get it done.

0:00:30So I'm sorry about that.

0:00:31If you were looking forward to an episode,

0:00:33hopefully I can make this one twice as good,

0:00:35and that'll hopefully offset that a little bit.

0:00:37So what I'm gonna be talking about today,

0:00:39and it'll be one topic for the whole show,

0:00:41it has a couple of different angles,

0:00:42but is essentially, I've been working on feed wrangler.

0:00:46I've been heading into the phase a little bit

0:00:48of starting to work on performance,

0:00:50and performance management, and kind of how to make things

0:00:53go, work in a more performant way, I guess.

0:00:55And so basically I was trying to think of a way

0:00:59that how I go about this is almost kind of rote now.

0:01:02Like I just kind of have a pattern and a phase I go into.

0:01:06And I was trying to think about why I do it that way

0:01:08and how I could kind of generalize that a little bit.

0:01:11And that's kind of what I'm gonna talk about now.

0:01:13And essentially what I've come up with is

0:01:15performances really can only be solved or improved

0:01:19in one of three ways.

0:01:20And they're very related and there's a little bit

0:01:21of overlap, but basically you can avoid work,

0:01:25can defer work, and you can remember work. Those are really

0:01:30the only three things you can do to make something faster. I'll

0:01:33kind of walk through them in in turn and then also kind of some

0:01:36thoughts I had that kind of come out of that. So the first one,

0:01:39you can avoid work. This is all about actually improving the, I

0:01:45guess you could call it the algorithmic complexity of what

0:01:47you're doing. So this is if you come from a CS background, this

0:01:52is one of those things that you can use is like the complexity

0:01:55of the algorithm or the efficiency of the algorithm, those types of things where you

0:01:58can actually avoid doing work. And if you're not, if you don't come up from a CS background,

0:02:03I highly recommend going and looking at any of a dozen, just search for like sorting algorithms.

0:02:08This is one of those funny things to remember from like, you know, sort of my early days

0:02:11in CS at college, where you talk about how the same operation, if you have a list of

0:02:16numbers and you want to sort them, you can do that sort in a variety of different ways.

0:02:21And the difference in complexity and the amount of effort and like operations it takes to

0:02:25do that can vary dramatically based on how you approach it.

0:02:29You know, you can go from things like quicksort and mergesort, which are what they call logarithmic

0:02:33complexity to things that, you know, I think there's sort of some sorting algorithms that

0:02:38are like cubic, which if those terms don't make any sense, like I said, go look at a

0:02:42sorting thing.

0:02:43But basically, the way you solve a problem can make, have a dramatic impact on the amount

0:02:48of time it takes or the resources it takes, probably more generally, it takes to do it.

0:02:54And so the first thing you can do is kind of see are there things that I'm doing here

0:02:57that I can avoid doing, that I can just not do, that I can improve my algorithm, my approach,

0:03:02that I can kind of take a different thing to it and that would improve the performance

0:03:09of my application.

0:03:10And if you can, then that's awesome.

0:03:12That's a great way to sort of like free, it's free, you know, in terms of you're not, all

0:03:17All you're getting, it's like you're just changing

0:03:19slightly how you do something,

0:03:21and the result is sort of almost all outside.

0:03:24The next area that you can do things is,

0:03:26I said you can defer things.

0:03:28And this is essentially ways of creating the appearance

0:03:32of performance without necessarily changing

0:03:35the amount of work you do.

0:03:37So if you've gotten to a point that your algorithm,

0:03:39your approach, the way you're tackling a problem

0:03:41is as efficient as possible,

0:03:44or as efficient as reasonably possible,

0:03:46thing you can do is you can start deferring work. And this is mostly about optimizing

0:03:50for the user's experience so that they have a perception of high speed interactivity,

0:03:57whatever it is, that things are going quicker, but whereas they may actually not be the case.

0:04:01Examples of that are, for example, on iOS is putting things into background threads

0:04:06using Grand Central Dispatch, those types of approaches where the main thread, the thing

0:04:11that the user is actually interacting with can be very performant. It can go do very

0:04:14very quickly responsive, all those types of things.

0:04:17But the app's actually doing a lot.

0:04:19It's just doing it in different threads away from the user

0:04:23so the user isn't aware of that work.

0:04:25So this is an example of things where

0:04:27you can take that operation and put it somewhere else

0:04:31in a way that can use.

0:04:31Say you're doing a big import.

0:04:33You do that off the main thread.

0:04:34You don't lock that up.

0:04:35The user has a perception of performance,

0:04:37even though that same amount of work is still getting done.

0:04:40Similarly, this is something that I've

0:04:42been working in a lot with Feed Wrangler,

0:04:44is in most web applications you can't do very much

0:04:48during the actual request.

0:04:49If it's any kind of long-lived process,

0:04:52you need to move it onto a background processor,

0:04:55something that is gonna be kind of working in the background

0:04:58and having the user interact with it in another way.

0:05:01And that's something that I've recently been

0:05:02getting into a lot with, you know,

0:05:04I think right now I'm using Sidekick,

0:05:05which is just a Rails backgrounding tool

0:05:07that seems to be really, really awesome.

0:05:09And what it allows you to do is you can say,

0:05:12okay, I need to do this long operation,

0:05:14I need to import from Google Reader,

0:05:16I'm gonna kick that off in the background,

0:05:18and then you can come back to the user and say,

0:05:19hey, I started, hey, I'm updating,

0:05:22oh, did some work, did some work, did some work.

0:05:24And you can create the effect of appearance

0:05:28of a lot of progress in a way that's much more useful

0:05:31and interesting to a user than if you just

0:05:33sort of had the request take longer,

0:05:36had it take 60 seconds to complete.

0:05:39Just not a good user experience.

0:05:40can put it off, you can delay it. And then the thirdly, and

0:05:44the third area that you can do is that you can remember work.

0:05:47And this is caching. I mean, I'm just I'm kind of turning it into

0:05:51you know, calling it, calling it in that name, because it's, you

0:05:55know, it's fits well with the structure of the others. But

0:05:57basically, it's just caching and caching is a very tricky

0:06:00problem. But it's also very powerful. And caching is just

0:06:02when you remember something you've done before, so that you

0:06:05don't have to do it again. It's a different kind of avoiding

0:06:09work because obviously you can avoid doing certain kinds of operations if that operation

0:06:14is already, if you've already done it once, you can just not do it again if you remember

0:06:19it. Now, caching is very complicated because you have to make sure that what you're doing

0:06:23is the exact same work that you're trying to avoid. So it's similar but subtly different

0:06:31could create all kinds of problems for you down the road.

0:06:33And then on the flip side of that, too, is caching can take a lot of other resources.

0:06:39You're not avoiding work.

0:06:40So I was saying at the beginning when if you avoid work, it's sort of free.

0:06:44It's not really coming at an additional cost, typically.

0:06:46You know, if you just use a more efficient algorithm or those types of things, there's

0:06:49usually not a lot of downside to that.

0:06:52With something like caching, though, you can create all kinds of downsides in terms of

0:06:55now you have to invalidate caches, you have to expire caches, you have to manage them.

0:06:59They can take a lot of space, which can annoy users.

0:07:02And so it's kind of a tricky thing to do.

0:07:04But overall, caching typically is a big win.

0:07:06It typically is something that lets

0:07:08you have a lot of benefits in terms of performance,

0:07:12because the time it takes to retrieve something

0:07:15is almost always going to be faster than the time it

0:07:17is to regenerate something, certainly

0:07:19for the kind of objects that you'd be looking to cache.

0:07:21And so that's kind of the three approaches

0:07:23that you can take to improving the performance of something.

0:07:25You can avoid it, you can defer it or delay it,

0:07:30and you can remember it for later.

0:07:32And in general, that's really all you can do.

0:07:37And so when I find myself in a performance cycle,

0:07:40when I'm finding myself stuck on something

0:07:42that I want to be faster, that I'm working on a problem

0:07:45and I'm like, you know, really, I want this to be more responsive.

0:07:47I want this to be faster.

0:07:49I want this to look better for the user.

0:07:50That's really the three things that I do.

0:07:52And I kind of work through them, generally speaking,

0:07:53in that order, that I'll try and see,

0:07:57is there a way that I can do this more efficiently?

0:07:59And often there is.

0:08:00Often there is, when I'm building something initially,

0:08:02what I'm doing is just attacking it from the most--

0:08:06I had a professor in college who always

0:08:07used to call it the naive solution.

0:08:09And the naive solution is usually the obvious one

0:08:12that gets the result the most--

0:08:14the result in the quickest in terms of your development time,

0:08:18but not the quickest in terms of the actual computational time.

0:08:21And so often I'll just build the naive solution,

0:08:23and that's fine.

0:08:24I'll build it, I'll deploy it, and then it

0:08:27gives me a good starting point from which I can work.

0:08:29And I'll say, hey, can I make this faster?

0:08:31Am I doing stuff here in a way that's silly?

0:08:33Am I iterating over something in ways

0:08:35that I really don't need to break out of this loop?

0:08:37Would that help this better?

0:08:38Can I split up the work?

0:08:40There's all kinds of things you can

0:08:41do to make something faster.

0:08:43And then once I've got to that point, then it's like, OK,

0:08:46well, this is how long this is going

0:08:47to take to do, no matter what.

0:08:49That's what I'm saying.

0:08:50This is as performant as can be.

0:08:52Is there a way that I can do this in a way

0:08:53that the user won't notice?

0:08:55Can I defer this off of the user's attention

0:08:58so that they don't have to worry about the time it's taking?

0:09:01And I'll try to work that out.

0:09:02Like I said, on iOS, almost always,

0:09:03it's going to be taking long operations

0:09:06and be moving them off the main thread,

0:09:08and then just reporting results back to the main thread.

0:09:10And that creates a tremendous boost

0:09:12in terms of perceived performance,

0:09:13even though the same amount of work is being done.

0:09:16And then the last area is going to be just caching.

0:09:17I'm going to say, OK, now that I've

0:09:20done this whole big chunk of work once,

0:09:22can I save it in such a way that I don't have to do it again? And

0:09:25that can come into a variety of different ways. This doesn't

0:09:28have to just be sort of something that's algorithmic. Of

0:09:31course, this is saving network saving network requests, you

0:09:35know, caching, you know, say in check the weather, I cache the

0:09:38latest weather report that I get for a particular GPS location.

0:09:42So that if you happen to ask for that same request again, 30

0:09:46seconds later, I'm just going to give it back to you because the

0:09:49weather hasn't changed in that last 30 seconds. And so you can

0:09:52do things like that, that just overall will increase the

0:09:55efficiency of your of your, of your system. It's also one thing

0:09:59that I wanted to kind of have a slight tangent on. It seemed

0:10:03off kind of interesting that those same three things apply, I

0:10:05think more generally also, to the way we approach work and

0:10:09work life. And by that, I mean, as I approach whatever it is,

0:10:13sorry, you could say productivity or just work in

0:10:17in general. If I start from an assumption that what I'm doing is worthwhile, interesting,

0:10:24useful, and important, there's only three ways that I can do to improve my productivity.

0:10:29I can either find ways to do what I do more efficiently. These are things that would improve

0:10:36the ability of whatever it is that I'm doing. This is like try writing code in Xcode versus

0:10:44in TextMate if you're doing iOS development.

0:10:46You're going to be a lot more productive probably in Xcode

0:10:49in terms of it does-- there's a lot of affordances and things

0:10:51that improve the efficiency of that process.

0:10:53You can defer work, which when I think of it in this way

0:10:55is taking it off the main thread is delegating, is outsourcing,

0:10:59is taking that work and having someone else do it.

0:11:01So this is having someone else do your taxes,

0:11:02having someone else do your help desk,

0:11:04having someone else do your graphic design, your icon

0:11:06design, having taken things where you can defer that work

0:11:09away from yourself in a way that increases your productivity,

0:11:13And then caching is an interesting thing when you try and apply it to yourself, because

0:11:17that makes me think about trying to be good about things like code reuse, which is a classic

0:11:24example of something like that, or even just kind of being mindful about how you work and

0:11:28remembering the mistakes you've made before and being kind of mindful of that so that

0:11:34you can avoid making the same mistake again.

0:11:36That can be in a formal way if you like.

0:11:38But generally for me, it's just something that I try and part of it, honestly, that's

0:11:41why I do this show is that it helps me to think through the mistakes I've made in a

0:11:44way that helps me avoid doing them in the future.

0:11:47And so that's getting a little bit esoteric, but that's just kind of something that I was

0:11:50thinking about as I was preparing this talk to talk about kind of how I do, how I go about

0:11:54performance.

0:11:55I think you can apply that same thing into a lot of different areas in your life.

0:11:58And the result is pretty good.

0:12:00Anyway, that's it for today's show.

0:12:02As always, if you have questions, comments, concerns, or complaints, I'm on Twitter @_DavidSmith.

0:12:06I'm on AppNet @DavidSmith.

0:12:07You can email me, david@developingperspective.com.

0:12:09Otherwise, you have a great week, happy coding, and I will talk to you later.