Profiling SwiftUI Apps with Instruments

A quality app not only looks good, it feels good too. This includes amazing animation, great design, amazing interactions, and perhaps most importantly, responsiveness.

When you hear the term “responsive,” you probably think of an app that always responds instantly to your actions. For example, when you scroll through a list in such an app, you won’t notice any delays, glitches, or jerks that would make the scrolling feel less like you’re in control.

As applications grow in size and complexity, it becomes increasingly difficult to solve performance problems using simple techniques such as using output operators, reading the code, and testing the application. Performance problems, like your application, become more complex — which means you need to use more sophisticated tools to profile and test fixes.

In this article, we'll look at how you can use Instruments to get new and interesting data about your app.

Building and running the application using Instruments

Once you decide you want to profile an application, you'll need to run it a little differently than usual. You'll need to compile the application by selecting the Profile option from the Product menu or by pressing the ⌘+I hotkey.

Changing the profile setting for a Xcode project

Changing Profile Settings for a Project in Xcode

By default, performing this action will create the application in Release mode. This means that the application you are profiling will be built using the same settings and configuration as the application you ship to your users.

Note: In this article, I will profile the application using the simulator. Instruments supports profiling applications running on your device. This Always The preferred approach when profiling an application. The simulator uses the hardware resources of your Mac. This means that the results in Instruments can sometimes differ significantly from what happens on the real device.

Once the app is created, the Instruments app will open and you can choose from different profiling templates. To profile a SwiftUI app, you'll start by choosing a SwiftUI template.

Selecting the SwiftUI template from Xcode

Selecting a SwiftUI template in Xcode

After selecting the template you are interested in, the main Instruments window will open. In the upper left corner is the record button. When you click it, your application will launch and Instruments will start profiling it.

SwiftUi development screenshot

At this point, you need to start interacting with the application and performing the actions you want to profile. During this process, Instruments will record various data. Once you have collected the data you are interested in, you can click the Stop button in the upper left corner of the Instruments window to end the recording.

Now that we have some data to analyze, let's explore the different bars of information that Instruments shows, starting from the top.

Exploring the View Body Strip

The topmost bar in SwiftUI Instrument is the View Body. SwiftUI records which view bodies were accessed and how long each access took. This information is presented in the View Body bar.

When you select this bar, Instruments will show you an overview of the view bodies that were evaluated during the entire recording period. If you expand the information specific to your application, you can see which yours views were evaluated. You'll also see how often each view subclass was evaluated, how long all the evaluations took together, and how long the fastest, slowest, and average calls to the view body took.

SwiftUi development screenshot

If you're interested in profiling a specific interaction, animation, or moment in time, this view is too broad. After all, it shows everything that happened during the entire recording period.

Luckily, you can zoom in on a specific portion of the recorded data. Click in the top bar and drag to select a time period. The bottom bar will now show only those body views that occurred during the selected time period.

Every time SwiftUI evaluates the body of a view, it says a few things:

  • One or more properties of the view have changed.

  • Or one or more observable objects in the view have triggered their objectWillChange publishers.

  • SwiftUI will do the work of redrawing this view.

Before SwiftUI evaluates the view body, it compares the views' properties to ensure that it is reasonable to assume that redrawing the view will result in a new visibility state.

So if you see more view bodies than you expected, or if you see view bodies where you're sure the data hasn't changed, you know what to look for. Something in your code is definitely changing in a way that causes this view to change one of its properties.

The tricky part is that there's a good chance that none of the view's properties actually changed. Or rather, none of the properties your view needs. If your view observes an observable but doesn't use some of its @Published properties, the view will still re-render when one of those unused @Published properties changes.

The View Bodies strip is a useful tool to help you understand if SwiftUI is doing more work than it should.

Exploring the View Properties Strip

The View Properties strip helps you see how your view properties are behaving. It displays the views, view properties, and the current value of those properties in a list. This allows you to check the current state of the application at the marker location shown in the image below.

SwiftUi development screenshot

Click on different points along the time span to see the current state values ​​at the marker location.

When one or more of your view's state-related properties are updated, you'll be able to see those values ​​change as you move the playhead. This is pretty handy, but unfortunately, you can't always clearly see which properties have changed in which view. You can only differentiate properties by their type, but it's not clear when two properties are on the same view instance or different ones.

This strip is useful to monitor, but it does not provide as much information as the body strip.

Understanding the Core Animation Commits Bar

The Core Animation Commits bar contains a bit of information. It shows how many Core Animation Commits our application has made in the selected time period, and how long those commits took.

SwiftUi development screenshot

This bar is especially useful for analysis if you are having UI performance issues and want to figure out if certain views are causing heavy Core Animation Commit operations. Core Animation Commit causes your device's GPU to do the work of redrawing or updating the screen. So when you see Core Animation Commit, you know you are dealing with redraws.

If you notice that there are a lot of commits happening, or commits are slow, look at the View Bodies lane to figure out which views are causing the problems. Which views are being redrawn during slow commits? If these views represent a huge area of ​​your layout, or if they are complex and have a large body, it might make sense to see if you can split the view into smaller views that observe less state.

Smaller views end up requiring less work to evaluate, and if they also take up less space in the interface, that means fewer pixels will need to be drawn.

The Core Animation Commits bar is very useful for finding and fixing major redraws, as it gives a pretty clear indication of resource-intensive UI work.

Understanding the Time Profiler Bar

The Time Profiler strip is very useful if you want to see what functions are called in your application during an animation, in response to a button click, or when evaluating the body of a view.

Time Profiler takes a snapshot of what's happening on your CPU at very short intervals. These intervals are so short that we can accurately determine how long a particular function call took. Because everything that happens on the CPU is captured, a huge amount of data accumulates in the Time Profiler strip.

Typically, you look at the functions that exist in your code to see which ones might be slow.

The best way to display custom code on the Time Profiler strip is to select it, click on the Call Tree at the bottom of the screen, and then select the following options:

SwiftUi development screenshot

These options give you a great overview of what's going on in your code in each thread. If you expand the Main Thread, you'll see something like this:

SwiftUi development screenshot

You will be able to see every function and closure that was run during the selected time period, as well as the duration of the code execution. Note that you will not be able to easily see the number of times a function was run, so it is best to select as small a time period as possible, in which you can analyze what exactly is happening in response to, for example, pressing a certain button.

In conclusion

Code profiling is an essential part of creating highly performant applications. Early in development, you can use common sense, your eyes, and a little refactoring to improve the performance of your application.

However, as your app grows in complexity, it will become increasingly difficult to confidently reason about everything your app can do at any given time. At this point, Instruments will serve as an indispensable tool to help you get detailed information about everything your SwiftUI app is doing.

Start by looking for slow view bodies or view bodies that are evaluated when you don’t expect them to. Then look at the Core Animation Commits bar to see if your actions are causing heavy repaints. Use View Properties to analyze property updates and make sure your app’s state looks more or less as expected. Finally, look at the Time Profiler to see if any functions can be optimized to run faster.

Instruments offers many other templates and profiling tools, so it is highly recommended to explore them as well. However, the SwiftUI template provides a great start for learning about your app's performance.


All current methods and tools for mobile (and not only) development can be mastered in OTUS online courses: in the catalog you can see the list of all programs, and in the calendar — sign up for open lessons.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *