This workshop will be retired on May 31, 2020.
Time Profiler13:15 with Josh Timonen
The Time Profiler catches stack traces on time intervals, seeing which processes are running during each slice. It collects and accumulates these samples to give us time quantities for processes within our app.
Time Profiler is a way to get some clear numbers and objective data on what is actually taking the most processing time in our apps.
- Catches stack traces on time intervals
- Sees what processes are running during each slice
- Collects time information for app processes
- Helps us make clear A/B comparisons
The time profiler catches stack traces on time intervals usually set to one 0:00 millisecond seeing which processes are running during each slice. 0:05 It collects and accumulates these samples to give us time quantities for 0:09 processes within our app. 0:14 This way we can see if our app is doing something that's consuming a lot of time 0:15 and we can make clear AB comparisons for our code changes and their effects. 0:20 First, let's launch the instruments app on its own. 0:25 This should bring up the selective profile template menu, but if it doesn't, 0:28 you can launch it from the top menu by selecting File > New. 0:33 We're going to be working with the Time Profiler template, select its icon and 0:36 then hit Choose. 0:41 This launch is the instrument workspace with the time profile or 0:44 instrument visible in the timeline. 0:47 To the right of the record and 0:49 pause buttons is the dropdown menu to select the device and app target. 0:50 So, you can launch into the time profile or instrument this way 0:55 as long as you have the app installed on the device or simulator. 0:59 But we'll be launching instruments through Xcode, which is usually much simpler. 1:03 So let's close instruments then open the sample Xcode 1:08 project provided with this workshop named Instruments Example. 1:11 Let's launch the app in the simulator. 1:21 We're running this workshop against the iPhone simulator, which will work for 1:26 our example. 1:29 But it's best to do your testing on a physical device. 1:30 Since the simulator has access to your computer's resources, 1:33 it's probably going to run smoother than when it's on a physical iPhone or iPad. 1:36 As you can see this app has a table view with images and labels in the cells, 1:41 and when you tap a row it launches another view controller 1:45 with a background image and a number. 1:48 In Xcode click on the debug navigator icon in the left panel. 1:56 Here will select CPU from the list 2:01 which brings up some CPU related information in the main window. 2:04 If we scroll up and down in our app while this window is open in Xcode 2:08 we can see that the CPU percentage used to dial updates on the fly 2:11 as well as the usage over time chart and a usage comparison dial 2:16 which displays our apps usage compared to the other running apps on the device. 2:21 Again, I should note that since this is running in the simulator which has 2:26 access to the computer's resources numbers like this CPU percent used 2:30 are going to be lower than they may be on an actual device. 2:35 Let's now click the Profile and Instruments button 2:40 in the top right corner, then select Transfer from the pop up. 2:43 This will transfer our current running app session to instruments. 2:47 Once we're up and running in instruments, scroll in our apps table view a bit and 2:51 data will start to come into the time profiler. 2:55 You'll see that the timeline and detail windows begin to populate with data. 3:07 Let's pause for a second. 3:12 The first thing we're going to want to do is set a few parameters 3:15 to make our debugging job easier. 3:18 First, make sure the details and inspector windows are visible they should both 3:21 be toggled on in the top right of the main toolbar. 3:25 In the lower details window, make sure we're displaying the Call Tree data. 3:28 If not select it from the dropdown in the top left of that lower window. 3:33 In the right inspector window, select the settings gear icon in its top menu. 3:37 Below in the list titled Call Tree, check the box for Hide System Libraries. 3:43 This will help isolate the code that is ours. 3:49 In the right Inspector window, if you select the first Settings tab icon, 3:52 the circle with the squiggly line, you'll see that you can adjust 3:56 the sample interval which is currently set to one millisecond. 4:00 This is how frequently the time profiler will take a new slice 4:04 when it catches each stack trace to see what is running. 4:08 A faster interval would make more slices and would theoretically give you better 4:11 data if you had very quick processes that maybe called very frequently, and 4:16 longer intervals would take fewer slices giving you less granularity. 4:21 For our purposes one millisecond is adequate and we'll leave it set there. 4:25 Now in the detail window data, you should see main thread listed. 4:30 If the row is not expanded out hit the arrow next to it to expand it 4:35 then expand out main beneath it. 4:40 This will display all of the relevant sub processes. 4:44 It's also good to tap the running time header on the far left column so 4:47 that the data is sorted by running time with the largest percentages at the top. 4:51 Now, let's unpause and let's scroll up and 4:56 down in the simulator tap to open the Detail View Controller, 4:58 go back, basically poke all around the app for a bit. 5:02 Once we've done that let's go back over to instruments and hit Stop. 5:18 Let's have a look at the data in the details window. 5:22 Here we can see that our THViewController is taking up a decent amount of time 5:25 in the cellForRowAtIndexPath and scrollViewDidScroll methods. 5:30 We can hit the Expand button next to scrollViewDidScroll and 5:35 see that our method background image with the size takes up a decent chunk of this 5:39 method's time. 5:44 If we double-tap that method, it displays the relevant code in our project. 5:45 We can see that in this method, we're creating a new UI image object every time, 5:51 and then doing a CG image operation to generate a cropped image. 5:56 On the right, it shows us that this line that creates the UIImage came up in 34 6:01 of its slices and the image with CGImage line came up in one slice. 6:05 This helps give us an idea of what is costing us the most CPU time. 6:11 The actual numbers you see in your instruments panel will likely vary 6:15 slightly from this test. 6:18 In the top of the Inspector Window tap the Call Tree button to go back to the list. 6:20 Let's double tap on scrollViewDidScroll 6:25 which we know is calling the background image with size method. 6:28 Looking at this code, we can see that the background image with size call line was 6:31 hit 42 times, the largest number in this method. 6:36 The creation of the UIImage view was hit five times and 6:39 the setting of the table views background view property was hit 36 times. 6:43 In the top right corner of the Inspector Window, 6:47 hit the Xcode icon button to jump back to Xcode and show us this code in the editor. 6:51 As you may notice we are setting this background image property on the table 6:57 view every time scrollViewDidScroll gets called, 7:01 which is going to happen constantly as the user scrolls. 7:04 Since the image isn't changing, let's move this code to viewDidLoad so 7:08 it only happens once. 7:12 Okay, now let's launch the app. 7:30 Then select the Debug Navigator on the left columns top menu. 7:37 Then select CPU, then Profile and Instruments. 7:41 We'll transfer the session and once instruments comes up for us we'll scroll 7:47 up and down in the app several times to collect some new scrolling data. 7:51 Let's go back to Instruments and pause. 8:06 We'll again want to select the display settings gear icon in the right Inspector 8:09 window and under Call Tree select Hide System Libraries and under the call 8:15 tree list in the detail window, we'll want to expand Main Thread and Main. 8:19 Since we moved all of that code out of scrollViewDidScroll we can see that it's 8:24 no longer a method that's registering in the time profiler slices. 8:29 Next we have the cellForRowAtIndex path method. 8:33 This is consuming about 16% of our running time at the moment. 8:37 Let's hit the Expand button on that line and 8:41 we can see that again the culprit is this background image with size method. 8:43 Let's double tap cell for row at index path to see the code. 8:48 Since cellForRowAtIndexPath is called each time a new cell comes on screen, 8:54 this method is going to get called a lot when the user is scrolling. 8:59 Let's tap the open in Xcode button in the top right of the Inspector panel and 9:03 see what we can do. 9:07 Since this image is the same on all cells, let's simplify things. 9:09 We'll make a cell background image property on THViewController. 9:14 Then let's set this image at the bottom of ViewDidLoad 9:27 using our BackgroundImageWithSize method. 9:30 Then in cellForRowAtIndex path, 9:48 we'll set the image on the cells image view to this new property, 9:50 instead of making the background image with size call every time. 9:55 Okay, great, so now this image is only created once and 9:59 is then set on each new cell during cellForRowAtIndex path. 10:04 Now, let's relaunch the app. 10:08 Then go back to the debug navigator then select CPU, Profile and 10:15 Instruments, then transfer session. 10:19 Let's pause for a second, as you've probably noticed 10:23 we have to update our settings each time we come back into instruments, 10:26 because it's generating a new template each time we transfer. 10:30 We actually wouldn't have to make all of these settings updates every 10:34 time if we saved the session or left an old one open, 10:38 and then relaunched it after the app has been installed to the device. 10:40 I've been using the transfer session option a lot, 10:44 since it's nice to move directly from Xcode to instruments. 10:47 But you can simply build the project in Xcode to your test device or 10:50 sim then open your template in Instruments and 10:54 select the device in the installed app from the top list, then record. 10:57 You just need to remember to always build the app first to the device or 11:02 sim with all of your latest changes before running and 11:06 then be sure to select the proper installed app. 11:10 So, for example, 11:13 we could close this session then go back to our last open session. 11:14 Select the right device we've been building to the iPhone6S running 9.3 and 11:19 then go down to the instruments example target under installed apps. 11:25 Now, if we hit record, we're running our latest version and 11:30 we have all of our customized settings in this window. 11:33 Let's scroll around and get some new data. 11:39 Let's pause. 11:52 In the call tree list we can see that cellForRowIndexPath is still listed, 11:55 but it's now lower around 8.9%. 12:01 The fact that it's still in the list is not surprising since generating and 12:04 dequeuing new cells is likely going to be the bulk of what's going on while we're 12:08 scrolling in a table view. 12:13 If we expand out that row, we can see that our background image with size method is 12:14 no longer there as we'd expect and now the largest method call it 12:19 lists is the cells init with style method which makes sense. 12:23 Lower in the list, we can see that view did load now comes up at 2% because 12:27 it's doing the background image with size call. 12:32 But that's fine it's taking up much less CPU time in that 12:35 one instance as opposed to the many times it was being called during scroll. 12:38 Great, so now we've significantly optimized these details in our demo app 12:43 and the time profile or 12:48 instrument is no longer showing any major issues in our app. 12:49 I hope this workshop has helped get your feet wet with time profiler and 12:53 instruments. 12:57 As we've seen it's a great way to get some clear numbers and 12:57 objective data on what's actually taking the most processing time in our apps. 13:00 It's not really as scary as it can seem at the outset. 13:05 Once you've run it a few times on your own apps you'll see how 13:09 powerful a tool it can be. 13:12 Thanks for watching. 13:14
You need to sign up for Treehouse in order to download course files.Sign up