#83: Performance and Letting Go.
00:00:00
◼
►
Hello and welcome to Developing Perspective. Developing Perspective is a podcast discussing
00:00:04
◼
►
news of note to my office development Apple and like I'm your host David Smith. I'm an
00:00:08
◼
►
independent iOS and Mac developer based in her Virginia. This is show number 83 and today
00:00:12
◼
►
is Thursday, September 27th. Developing perspective is never longer than 15 minutes. So let's
00:00:17
◼
►
get started. Alright, so this is gonna be another one in the series of episodes I went
00:00:23
◼
►
to. I'm going to be talking about the weather app I'm working on. And I'm kind of excited
00:00:27
◼
►
because I think I'm ready to ship.
00:00:32
◼
►
And I'm recording this about 3 p.m. on Thursday,
00:00:35
◼
►
and I'll probably be submitting this evening.
00:00:39
◼
►
I did the always exciting thing where I take the version number
00:00:42
◼
►
of my app and bump it all up to 1.0, which is kind of exciting.
00:00:45
◼
►
I think it's basically ready.
00:00:50
◼
►
I've done my initial beta testing.
00:00:51
◼
►
I've done as much testing as I can.
00:00:53
◼
►
I have nothing left on my to-do list.
00:00:53
◼
►
And so I think it's just about ready.
00:00:55
◼
►
So I'll talk a little bit more about that later in the show.
00:00:58
◼
►
But to start with, I was going to talk about one of the activities
00:01:01
◼
►
that you'll do towards the end of actual app construction.
00:01:04
◼
►
And that's performance improvements and performance testing.
00:01:07
◼
►
And it's vitally important and kind of a tricky problem.
00:01:11
◼
►
And so that's why I was devoted at least half the show to kind of just
00:01:14
◼
►
talking about how I go about that and what that looks like.
00:01:17
◼
►
So performance is most often just sort of--
00:01:19
◼
►
you characterize it as making your app do the things it does quickly.
00:01:25
◼
►
And quickly is ideally defined as imperceptibly fast.
00:01:30
◼
►
So the goal would be that ideally the user never really is aware
00:01:34
◼
►
that any operation is taking time to perform.
00:01:36
◼
►
It just happens.
00:01:37
◼
►
It's instantaneous as far as possible.
00:01:42
◼
►
And there's a lot of tricks and things you can do to create either
00:01:46
◼
►
that illusion or performance enhancing techniques
00:01:51
◼
►
and approaches that you can do to make that the actual case.
00:01:54
◼
►
And so what I've done essentially is,
00:01:59
◼
►
as I've talked about, I've built the app,
00:02:01
◼
►
I prototyped it, I worked on the fun,
00:02:03
◼
►
sort of scaling on the feature set,
00:02:05
◼
►
understand exactly what it is I'm going to build,
00:02:07
◼
►
and then I started this process of refinement.
00:02:09
◼
►
And you kind of want to think about this as,
00:02:12
◼
►
if you've ever done carpentry with a sandpaper, right,
00:02:14
◼
►
where you're going to sit down and you have the basic form,
00:02:17
◼
►
it's right there, and all you're going to do
00:02:19
◼
►
is take some sandpaper and you're going to
00:02:22
◼
►
be starting to smooth it off.
00:02:23
◼
►
And your goal is to make it as silky smooth as possible.
00:02:26
◼
►
And the way you, if you've ever done any carpentry,
00:02:29
◼
►
the way that you go about doing that is you start off
00:02:31
◼
►
with a really rough sandpaper.
00:02:34
◼
►
And your goal is you're taking off big chunks of wood
00:02:37
◼
►
at a time, you're kind of really,
00:02:39
◼
►
you're not worried as much about the precision of that,
00:02:42
◼
►
you're just kind of going at it.
00:02:43
◼
►
And then as you get closer and closer to what you're trying to do, you're going to get finer
00:02:47
◼
►
and finer sandpaper, and you're going to be doing smaller and smaller adjustments.
00:02:51
◼
►
That's very similar to the approach I end up taking with performance improvement.
00:02:56
◼
►
What I want to do is, I want to start off with making any kind of huge improvements,
00:03:03
◼
►
big chunks, things that are going to have very big improvements and obvious advantages
00:03:08
◼
►
to the user.
00:03:09
◼
►
I want to do those first.
00:03:10
◼
►
and I want to get the groundwork of that going.
00:03:13
◼
►
And so the way I typically approach that is I'll just use the app
00:03:17
◼
►
and I'll be like, "Man, that's slow,"
00:03:19
◼
►
and just sort of start an approach on some particular small area of the app
00:03:24
◼
►
or some focused area of the app.
00:03:26
◼
►
The number one rule of performance improvement is measurement.
00:03:29
◼
►
If you don't measure what you're doing,
00:03:31
◼
►
you're probably going to drive yourself crazy
00:03:33
◼
►
and you're not really going to make progress on what's happening.
00:03:36
◼
►
By measurement, what I typically mean is either in instruments,
00:03:39
◼
►
instruments, looking at whatever memory performance, frames
00:03:42
◼
►
per second, the time profilers, stack trace,
00:03:46
◼
►
like those types of things.
00:03:48
◼
►
Or even just something as simple as grabbing the time
00:03:51
◼
►
before and after an operation completes
00:03:53
◼
►
and NS logging that to the console.
00:03:56
◼
►
But if you don't have a measurement of what your baseline
00:03:58
◼
►
is, then it's impossible to know if the improvements you're
00:04:01
◼
►
making are actually doing anything.
00:04:03
◼
►
And you'll just end up chasing your tail.
00:04:05
◼
►
If you're like, well, I think I changed-- when I made this
00:04:07
◼
►
change, I think that helped.
00:04:09
◼
►
But maybe I'll do this other thing, too.
00:04:10
◼
►
I may be able to do this other thing.
00:04:12
◼
►
And then the second rule is that you,
00:04:15
◼
►
in addition to measuring everything,
00:04:17
◼
►
you want to only ever change one thing at a time.
00:04:22
◼
►
And these two things go together,
00:04:23
◼
►
and they should make sense, that if you are changing two things
00:04:27
◼
►
at once, then you'll never know what's actually changing.
00:04:30
◼
►
Or worse, you make lots of changes at once
00:04:32
◼
►
and then kind of run through the app.
00:04:34
◼
►
It's almost impossible at that point
00:04:36
◼
►
to get a good sense of actually what's happening.
00:04:39
◼
►
And you're just going to drive yourself crazy.
00:04:41
◼
►
So for a performance measurement, like I said,
00:04:43
◼
►
I'll use a lot of instruments for a lot of it.
00:04:46
◼
►
And then the second thing that I do
00:04:48
◼
►
is just these print lines, and I'll
00:04:49
◼
►
have those all over the place.
00:04:51
◼
►
And so the first thing that I tackle--
00:04:53
◼
►
and this is probably, honestly, in my opinion,
00:04:56
◼
►
the most important thing that you
00:04:59
◼
►
can do for performance testing and improvement
00:05:03
◼
►
is that you want to focus on launch time.
00:05:05
◼
►
I think it's probably the most important bit of performance.
00:05:10
◼
►
I guess to me it's a bit strong.
00:05:12
◼
►
But it is certainly one of the most important areas
00:05:15
◼
►
of performance in your application
00:05:16
◼
►
because it's the user's first impression.
00:05:18
◼
►
And it's an impression that they're
00:05:20
◼
►
going to be making over and over and over again.
00:05:22
◼
►
Now, I know the app goes into a background state
00:05:24
◼
►
and may not actually be relaunched a lot.
00:05:26
◼
►
But I want that app's launch screen
00:05:29
◼
►
to disappear as quickly as possible.
00:05:31
◼
►
And the reason for that is that is, by definition,
00:05:34
◼
►
time that the user is wasting.
00:05:36
◼
►
There are a couple of areas in your app where it may be great
00:05:39
◼
►
or it can be faster at downloading stuff, faster
00:05:42
◼
►
at this, faster at that.
00:05:43
◼
►
But often those things are happening
00:05:45
◼
►
while the user can do something else
00:05:47
◼
►
or is looking at something else.
00:05:49
◼
►
But with launch time, that's it.
00:05:51
◼
►
All they can do is wait.
00:05:52
◼
►
They can't do anything else while that happens.
00:05:54
◼
►
So you want to make that as fast as possible.
00:05:57
◼
►
And the first rule of making your launch time fast
00:06:00
◼
►
is doing almost nothing on the main thread
00:06:04
◼
►
from application did finish launching to view did load,
00:06:08
◼
►
view did appear.
00:06:09
◼
►
And hopefully those terms make sense
00:06:10
◼
►
if you're an app developer.
00:06:11
◼
►
But basically from when your app starts
00:06:13
◼
►
until you have shown things and so you finish showing something
00:06:16
◼
►
on the screen, whatever that first thing is,
00:06:18
◼
►
you want to do as little as possible on the main thread.
00:06:21
◼
►
You want to put off as much as possible.
00:06:23
◼
►
You want to do as few-- the absolute minimum that you can.
00:06:26
◼
►
And that typically works out pretty well
00:06:28
◼
►
by just wrapping up code blocks, things that you need to do,
00:06:31
◼
►
and GCD queues, or just doing things where you can say,
00:06:35
◼
►
dispatch async on the main thread.
00:06:38
◼
►
And you're pushing these things off.
00:06:40
◼
►
So if you need them to happen up front,
00:06:42
◼
►
you need to do these things right away, do them early,
00:06:45
◼
►
but don't do them until you've started
00:06:47
◼
►
showing something to the user.
00:06:50
◼
►
It's just really important that you don't do that.
00:06:53
◼
►
And then the second thing that I do
00:06:55
◼
►
is you're trying to optimize that first view stack
00:06:59
◼
►
that you're going to show the user.
00:07:01
◼
►
And so being careful about what you're showing, how you do it,
00:07:05
◼
►
and the data you load and the data you need
00:07:07
◼
►
is all an important part of that.
00:07:09
◼
►
And I know for what I went through this process in my app,
00:07:13
◼
►
and I was able to get the launch experience on a 4S
00:07:18
◼
►
down in my naive, basic, simple solution.
00:07:21
◼
►
At one point, I think my launch time was about 2 and 1/2
00:07:25
◼
►
And I got it down to about 0.3 seconds
00:07:29
◼
►
by a lot of these things.
00:07:31
◼
►
So all those different things in aggregate.
00:07:32
◼
►
And then I was pleasantly surprised
00:07:34
◼
►
that when I got my iPhone 4-- or my iPhone 5,
00:07:38
◼
►
my launch time is now down to 0.1 seconds, which
00:07:43
◼
►
if you think about how short of a time that is,
00:07:46
◼
►
it's basically instantaneous.
00:07:48
◼
►
And it looks basically like the app launches immediately,
00:07:52
◼
►
which I'm really, really proud of.
00:07:54
◼
►
And I really like that part of it.
00:07:55
◼
►
That's something that I'm-- it's like I show off to people.
00:07:58
◼
►
It's like, let me quit the app in the multitasking
00:08:01
◼
►
and then started. Wow, see how fast that was. That's important to me because at no time
00:08:05
◼
►
someone on an iPhone 5 should ever have to wait a perceptible amount of time for the
00:08:12
◼
►
app to load. Another thing I'll say about this is I fall firmly in the camp of you want
00:08:18
◼
►
your launch image to be the empty state of your initial screen rather than a splash screen
00:08:25
◼
►
or a banner or a logo.
00:08:27
◼
►
And a big part of that is that really helps with the perceived
00:08:32
◼
►
load time of the application, because that
00:08:35
◼
►
will show instantaneously.
00:08:36
◼
►
And so it shows that, and then it shows your app.
00:08:39
◼
►
And so if those two things are the same,
00:08:42
◼
►
it almost looks like your app's loaded immediately.
00:08:45
◼
►
And just that extra 0.1, 0.2, 0.3 of a second
00:08:48
◼
►
that it took to actually load is just almost
00:08:51
◼
►
like you can make it look like an animation,
00:08:53
◼
►
that it was a launching animation, like your display is just fading in, rather than you
00:08:58
◼
►
actually were doing stuff in the background.
00:09:01
◼
►
So those are some of the things I do about performance. Basically, you just want to measure,
00:09:05
◼
►
and you want to change one thing. You just keep doing that, and you keep getting finer
00:09:09
◼
►
and finer grain. I mean, towards the end, I was changing just tiny little things, tweaking
00:09:13
◼
►
the way that I was saving files to disk, saving the way that the data structures that I was
00:09:20
◼
►
working with that I was saving the disk and my caching infrastructure. Anything that I
00:09:25
◼
►
could do to just squeeze and squeeze and squeeze, making sure that all of my networking calls
00:09:30
◼
►
as much as possible are gzipped so that I'm loading a small amount of data as possible,
00:09:35
◼
►
trying a bunch of different JSON libraries and frameworks to find the one that would
00:09:39
◼
►
work the best with my dataset. Because of course, typically, in my experience,
00:09:43
◼
►
NSJSON serialization, like the built-in one to the system, is pretty good. And in this
00:09:48
◼
►
In this case, for me, it actually turned out that was the best.
00:09:50
◼
►
But in my experience, it's possible that another library could be faster
00:09:56
◼
►
based on your data set, because they're all probably going to--
00:09:58
◼
►
they're making certain assumptions.
00:09:59
◼
►
They're all making different adjustments and things,
00:10:01
◼
►
how they're going to handle different encodings,
00:10:03
◼
►
how they're going to handle different data structures.
00:10:05
◼
►
And so you just-- you have to try these things to see which one's faster for you,
00:10:09
◼
►
not just which one's fastest based on benchmarks.
00:10:12
◼
►
And in the end, I'm very pleased with the performance of the app.
00:10:14
◼
►
I think it's fast. It's snappy.
00:10:16
◼
►
I was able to, on the 4S and 5, I have 60 frames a second animations everywhere.
00:10:22
◼
►
On the 4, I was able to get it to 40 frames a second, where at that point
00:10:25
◼
►
I just gave up.
00:10:26
◼
►
Because it's pretty smooth, but I couldn't quite get it more.
00:10:29
◼
►
And increasing-- the 4 is probably my performance baseline.
00:10:33
◼
►
And it is pretty good.
00:10:35
◼
►
It's visually smooth, but not as smooth as possible.
00:10:39
◼
►
And so that's kind of where I drew the line.
00:10:41
◼
►
But it's an important thing for performance.
00:10:43
◼
►
You don't want to go crazy and just constantly--
00:10:45
◼
►
Could we go down this rabbit hole?
00:10:47
◼
►
But once you ever get that good enough phase, it's great.
00:10:50
◼
►
And I think, like the app, I'm really
00:10:52
◼
►
proud of the performance of it just across the board.
00:10:55
◼
►
And so that brings me to the next thing.
00:10:57
◼
►
It's like I said, I'm basically getting ready to submit.
00:11:00
◼
►
The app I said is-- I think I mentioned before--
00:11:02
◼
►
is going to launch hopefully on October 17,
00:11:06
◼
►
which is in about 2 and 1/2 weeks-ish.
00:11:08
◼
►
It's about three weeks from yesterday.
00:11:10
◼
►
And I'm picking a date that's based on a variety of things.
00:11:13
◼
►
it's making sure I have enough time for app review to go through.
00:11:17
◼
►
And the way I tend to do it is I try and leave about two and a half weeks of time.
00:11:22
◼
►
App review on the iOS side has recently and typically been about a week.
00:11:26
◼
►
And so what I want to make sure is I always have enough time in it for two review cycles.
00:11:31
◼
►
So that's A, if they reject it for whatever reason, I mean, you never know.
00:11:36
◼
►
Like for some reason there's some weird bug that they find.
00:11:39
◼
►
You just got to account for that.
00:11:41
◼
►
And then two, it's so that if I submit it, they approve it,
00:11:46
◼
►
and I find a bug, I find a problem, a beta tester,
00:11:51
◼
►
a previewer, someone in the press finds some bug
00:11:55
◼
►
that I want out, I have an opportunity to resubmit
00:11:57
◼
►
and have that approved, hopefully, by the time
00:12:00
◼
►
that I'm aiming to launch.
00:12:02
◼
►
I'm picking a day specifically, so I can hopefully
00:12:04
◼
►
coordinate some marketing, some press, reaching out
00:12:06
◼
►
to my friends and colleagues and people to try
00:12:07
◼
►
I find building some buzz and promotion around it,
00:12:10
◼
►
and I find having a day in mind is very helpful for that,
00:12:13
◼
►
rather than just like, it'll launch at some point
00:12:15
◼
►
whenever it gets approved.
00:12:17
◼
►
And so I've set the release date to October 17th.
00:12:20
◼
►
Hopefully that ends up working out.
00:12:22
◼
►
Like I said, I'm submitting now.
00:12:24
◼
►
That's about three weeks.
00:12:25
◼
►
It should hopefully be OK in terms
00:12:27
◼
►
of getting that through App Review by then.
00:12:29
◼
►
But you just never know.
00:12:31
◼
►
But the funniest part, as I've been heading down this road,
00:12:33
◼
►
and it's been exciting, and I'm like, yeah, I'm getting close.
00:12:36
◼
►
narrowing in on finally being able to ship this thing.
00:12:39
◼
►
The hardest part, honestly, is letting go and trying not to feel overly protective of an application.
00:12:50
◼
►
So I've spent a good amount of time, it's probably about four weeks of work at this point,
00:12:55
◼
►
which is not a huge project, but it's a substantial investment in time and energy
00:13:00
◼
►
and various things I've bought in terms of graphics and fonts and all kinds of stuff to go into it.
00:13:05
◼
►
But there's something scary about letting other people see it.
00:13:10
◼
►
There's something scary about having other people look at it, and especially other people
00:13:16
◼
►
to critique it, to say what they think about it.
00:13:19
◼
►
Because obviously I think it's great, and you start off showing it to people who you
00:13:25
◼
►
So if you start off with people who love you, your family, your spouse, those types of people,
00:13:31
◼
►
And then you tend to move out to people who like you, your friends.
00:13:35
◼
►
And then you start to get into the scary part where you start to get into the people you
00:13:39
◼
►
respect or hopefully the people who respect you, which is starting to get into your colleagues.
00:13:45
◼
►
And that's where it really gets scary because these are people whose opinion you know is
00:13:49
◼
►
more honest and whose opinion you value in a way that is different than you would value
00:13:55
◼
►
your spouse.
00:13:56
◼
►
Not that I don't value my spouse's opinion, but it's a different kind of validation.
00:14:01
◼
►
Because when she says she likes what I'm doing, she's liking not just the app itself.
00:14:06
◼
►
It's in the context of all the work I've put into it, in the context of all the decisions we've jointly made about it, and so on.
00:14:13
◼
►
And so it's always a tricky thing.
00:14:22
◼
►
But I'm just going to encourage everybody to, you have to let go.
00:14:22
◼
►
to let go. You just have to understand that at some point you have to sort of let the
00:14:26
◼
►
bird fly free or whatever and just trust that you've made the right choices and hope that
00:14:31
◼
►
it goes well. That's kind of the scary point that I am now and I'm starting to send out
00:14:35
◼
►
beta testing and getting feedback and overall it's been positive, but it's just a scary
00:14:39
◼
►
point and I just wanted to voice that because I suspect many people feel that, that you
00:14:43
◼
►
just kind of have this timidness to show it to anybody, but ultimately that's probably
00:14:47
◼
►
going to be counterproductive. You just have to let go.
00:14:50
◼
►
Alright, that's it for today's show.
00:14:52
◼
►
As always, if you have questions, comments, concerns, I'm on Twitter @_DavidSmith.
00:14:56
◼
►
And otherwise, if you have a great weekend, happy coding, and I'll talk to you on Tuesday.