PodSearch

Developing Perspective

#117: Avoid, Defer, Remember.

 

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

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

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

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

00:00:18 ◼   ► so let's get going.

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

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

00:00:27 ◼   ► It was painted, all kinds of things,

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

00:00:30 ◼   ► So I'm sorry about that.

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

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

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

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

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

00:00:41 ◼   ► it has a couple of different angles,

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

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

00:00:48 ◼   ► of starting to work on performance,

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

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

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

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

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

00:01:06 ◼   ► And I was trying to think about why I do it that way

00:01:08 ◼   ► and how I could kind of generalize that a little bit.

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

00:01:13 ◼   ► And essentially what I've come up with is

00:01:15 ◼   ► performances really can only be solved or improved

00:01:19 ◼   ► in one of three ways.

00:01:20 ◼   ► And they're very related and there's a little bit

00:01:21 ◼   ► of overlap, but basically you can avoid work,

00:01:25 ◼   ► can defer work, and you can remember work. Those are really

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

00:01:33 ◼   ► kind of walk through them in in turn and then also kind of some

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

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

00:01:45 ◼   ► guess you could call it the algorithmic complexity of what

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

00:01:52 ◼   ► is one of those things that you can use is like the complexity

00:01:55 ◼   ► of the algorithm or the efficiency of the algorithm, those types of things where you

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

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

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

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

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

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

00:02:25 ◼   ► do that can vary dramatically based on how you approach it.

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

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

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

00:02:42 ◼   ► sorting thing.

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

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

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

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

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

00:03:09 ◼   ► of my application.

00:03:10 ◼   ► And if you can, then that's awesome.

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

00:03:17 ◼   ► All you're getting, it's like you're just changing

00:03:19 ◼   ► slightly how you do something,

00:03:21 ◼   ► and the result is sort of almost all outside.

00:03:24 ◼   ► The next area that you can do things is,

00:03:26 ◼   ► I said you can defer things.

00:03:28 ◼   ► And this is essentially ways of creating the appearance

00:03:32 ◼   ► of performance without necessarily changing

00:03:35 ◼   ► the amount of work you do.

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

00:03:39 ◼   ► your approach, the way you're tackling a problem

00:03:41 ◼   ► is as efficient as possible,

00:03:44 ◼   ► or as efficient as reasonably possible,

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

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

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

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

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

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

00:04:14 ◼   ► very quickly responsive, all those types of things.

00:04:17 ◼   ► But the app's actually doing a lot.

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

00:04:23 ◼   ► so the user isn't aware of that work.

00:04:25 ◼   ► So this is an example of things where

00:04:27 ◼   ► you can take that operation and put it somewhere else

00:04:31 ◼   ► in a way that can use.

00:04:31 ◼   ► Say you're doing a big import.

00:04:33 ◼   ► You do that off the main thread.

00:04:34 ◼   ► You don't lock that up.

00:04:35 ◼   ► The user has a perception of performance,

00:04:37 ◼   ► even though that same amount of work is still getting done.

00:04:40 ◼   ► Similarly, this is something that I've

00:04:42 ◼   ► been working in a lot with Feed Wrangler,

00:04:44 ◼   ► is in most web applications you can't do very much

00:04:48 ◼   ► during the actual request.

00:04:49 ◼   ► If it's any kind of long-lived process,

00:04:52 ◼   ► you need to move it onto a background processor,

00:04:55 ◼   ► something that is gonna be kind of working in the background

00:04:58 ◼   ► and having the user interact with it in another way.

00:05:01 ◼   ► And that's something that I've recently been

00:05:02 ◼   ► getting into a lot with, you know,

00:05:04 ◼   ► I think right now I'm using Sidekick,

00:05:05 ◼   ► which is just a Rails backgrounding tool

00:05:07 ◼   ► that seems to be really, really awesome.

00:05:09 ◼   ► And what it allows you to do is you can say,

00:05:12 ◼   ► okay, I need to do this long operation,

00:05:14 ◼   ► I need to import from Google Reader,

00:05:16 ◼   ► I'm gonna kick that off in the background,

00:05:18 ◼   ► and then you can come back to the user and say,

00:05:19 ◼   ► hey, I started, hey, I'm updating,

00:05:22 ◼   ► oh, did some work, did some work, did some work.

00:05:24 ◼   ► And you can create the effect of appearance

00:05:28 ◼   ► of a lot of progress in a way that's much more useful

00:05:31 ◼   ► and interesting to a user than if you just

00:05:33 ◼   ► sort of had the request take longer,

00:05:36 ◼   ► had it take 60 seconds to complete.

00:05:39 ◼   ► Just not a good user experience.

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

00:05:44 ◼   ► the third area that you can do is that you can remember work.

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

00:05:51 ◼   ► you know, calling it, calling it in that name, because it's, you

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

00:05:57 ◼   ► basically, it's just caching and caching is a very tricky

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

00:06:02 ◼   ► when you remember something you've done before, so that you

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

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

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

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

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

00:06:31 ◼   ► could create all kinds of problems for you down the road.

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

00:06:39 ◼   ► You're not avoiding work.

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

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

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

00:06:49 ◼   ► usually not a lot of downside to that.

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

00:06:55 ◼   ► now you have to invalidate caches, you have to expire caches, you have to manage them.

00:06:59 ◼   ► They can take a lot of space, which can annoy users.

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

00:07:04 ◼   ► But overall, caching typically is a big win.

00:07:06 ◼   ► It typically is something that lets

00:07:08 ◼   ► you have a lot of benefits in terms of performance,

00:07:12 ◼   ► because the time it takes to retrieve something

00:07:15 ◼   ► is almost always going to be faster than the time it

00:07:17 ◼   ► is to regenerate something, certainly

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

00:07:21 ◼   ► And so that's kind of the three approaches

00:07:23 ◼   ► that you can take to improving the performance of something.

00:07:25 ◼   ► You can avoid it, you can defer it or delay it,

00:07:30 ◼   ► and you can remember it for later.

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

00:07:37 ◼   ► And so when I find myself in a performance cycle,

00:07:40 ◼   ► when I'm finding myself stuck on something

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

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

00:07:47 ◼   ► I want this to be faster.

00:07:49 ◼   ► I want this to look better for the user.

00:07:50 ◼   ► That's really the three things that I do.

00:07:52 ◼   ► And I kind of work through them, generally speaking,

00:07:53 ◼   ► in that order, that I'll try and see,

00:07:57 ◼   ► is there a way that I can do this more efficiently?

00:07:59 ◼   ► And often there is.

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

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

00:08:06 ◼   ► I had a professor in college who always

00:08:07 ◼   ► used to call it the naive solution.

00:08:09 ◼   ► And the naive solution is usually the obvious one

00:08:12 ◼   ► that gets the result the most--

00:08:14 ◼   ► the result in the quickest in terms of your development time,

00:08:18 ◼   ► but not the quickest in terms of the actual computational time.

00:08:21 ◼   ► And so often I'll just build the naive solution,

00:08:23 ◼   ► and that's fine.

00:08:24 ◼   ► I'll build it, I'll deploy it, and then it

00:08:27 ◼   ► gives me a good starting point from which I can work.

00:08:29 ◼   ► And I'll say, hey, can I make this faster?

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

00:08:33 ◼   ► Am I iterating over something in ways

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

00:08:37 ◼   ► Would that help this better?

00:08:38 ◼   ► Can I split up the work?

00:08:40 ◼   ► There's all kinds of things you can

00:08:41 ◼   ► do to make something faster.

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

00:08:46 ◼   ► well, this is how long this is going

00:08:47 ◼   ► to take to do, no matter what.

00:08:49 ◼   ► That's what I'm saying.

00:08:50 ◼   ► This is as performant as can be.

00:08:52 ◼   ► Is there a way that I can do this in a way

00:08:53 ◼   ► that the user won't notice?

00:08:55 ◼   ► Can I defer this off of the user's attention

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

00:09:01 ◼   ► And I'll try to work that out.

00:09:02 ◼   ► Like I said, on iOS, almost always,

00:09:03 ◼   ► it's going to be taking long operations

00:09:06 ◼   ► and be moving them off the main thread,

00:09:08 ◼   ► and then just reporting results back to the main thread.

00:09:10 ◼   ► And that creates a tremendous boost

00:09:12 ◼   ► in terms of perceived performance,

00:09:13 ◼   ► even though the same amount of work is being done.

00:09:16 ◼   ► And then the last area is going to be just caching.

00:09:17 ◼   ► I'm going to say, OK, now that I've

00:09:20 ◼   ► done this whole big chunk of work once,

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

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

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

00:09:31 ◼   ► course, this is saving network saving network requests, you

00:09:35 ◼   ► know, caching, you know, say in check the weather, I cache the

00:09:38 ◼   ► latest weather report that I get for a particular GPS location.

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

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

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

00:09:52 ◼   ► do things like that, that just overall will increase the

00:09:55 ◼   ► efficiency of your of your, of your system. It's also one thing

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

00:10:03 ◼   ► off kind of interesting that those same three things apply, I

00:10:05 ◼   ► think more generally also, to the way we approach work and

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

00:10:13 ◼   ► sorry, you could say productivity or just work in

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

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

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

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

00:10:44 ◼   ► in TextMate if you're doing iOS development.

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

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

00:10:51 ◼   ► that improve the efficiency of that process.

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

00:10:55 ◼   ► is taking it off the main thread is delegating, is outsourcing,

00:10:59 ◼   ► is taking that work and having someone else do it.

00:11:01 ◼   ► So this is having someone else do your taxes,

00:11:02 ◼   ► having someone else do your help desk,

00:11:04 ◼   ► having someone else do your graphic design, your icon

00:11:06 ◼   ► design, having taken things where you can defer that work

00:11:09 ◼   ► away from yourself in a way that increases your productivity,

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

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

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

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

00:11:34 ◼   ► you can avoid making the same mistake again.

00:11:36 ◼   ► That can be in a formal way if you like.

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

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

00:11:44 ◼   ► way that helps me avoid doing them in the future.

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

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

00:11:54 ◼   ► performance.

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

00:11:58 ◼   ► And the result is pretty good.

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

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

00:12:06 ◼   ► I'm on AppNet @DavidSmith.

00:12:07 ◼   ► You can email me, david@developingperspective.com.

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