PodSearch

Developing Perspective

#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:24   seconds.

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:24   know.

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.