#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.