Ice-Breaking your swift code to detect lagging methods with Signpost

Amit Nadir
4 min readJan 17, 2023

--

Your app runs well but you have doubts or you see some functions lagging. Maybe it’s not good enough? How can you measure your code performance? There are few handy tools in Xcode, such as using the measure method in Unit Tests

From Apple documentation:

A performance test takes a block of code that you want to evaluate and runs it ten times, collecting the average execution time and the standard deviation for the runs. The averaging of these individual measurements form a value for the test run that can then be compared against a baseline to evaluate success or failure.

Ok that’s nice, but which method should you check? which one is lagging? and if the method is using network activity such as API request and response parsing, tests will be less handy to use.

So let’s break the ice! useful tool to start with is Signpost:

Signposts allow you to measure your app’s tasks using the same subsystems and categories that you use for logging.

Here is a quick guide for Signpost basics.

First, add import os.signpost in the class you want to measure.

Now lets create instance of OSLog:

let logMyMethod = OSLog(subsystem: "com.signpost.demo", category: "MyMethod")

Second, add a os_signpost method with .begin and .end in each method you want to measure. Lets assume for example we measure three methods that calls each other in synchronically like this:

MyFirstMethod() -> MySecondMethod() -> MyThirdMethod()

Each one is doing some work, which here was simulated by sleep function:

import UIKit
import os.signpost

class ViewController: UIViewController {

let logMyMethod = OSLog(subsystem: "com.signpost.demo", category: "MyMethod")

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
MyFirstMethod()
}


func MyFirstMethod(){
os_signpost(.begin, log: logMyMethod, name: "MyFirstMethod")
//
sleep(1)
//
os_signpost(.end, log: logMyMethod, name: "MyFirstMethod")
MySecondMethod()
}

func MySecondMethod(){
os_signpost(.begin, log: logMyMethod, name: "MySecondMethod")
//
sleep(2)
//
os_signpost(.end, log: logMyMethod, name: "MySecondMethod")
MyThirdMethod()
}

func MyThirdMethod(){
os_signpost(.begin, log: logMyMethod, name: "MyThirdMethod")
//
sleep(1)
//
os_signpost(.end, log: logMyMethod, name: "MyThirdMethod")
}

}Open Instruments:

Now let’s measure it using Instruments tools. Go to Xcode menu -> “Open Developer Tool” -> “Instruments”:

Choose profiling template “Blank”:

Tap on the plus icon on the right side of the instruments window, filter os_signpost object and drag it into the trace area:

Make sure to connect your device to the app to be measured:

After clicking the record button and running you will accomplish trace analysis:

We can notice in the summary table under the “MyMethod” category that we defined, how many times each method was called, the duration and some statics measuring the performance. We can easily see if some method is lagging way too much then we expected, or it’s being called few times and not only once as expected. Try profiling your own code with these simple steps to get some idea whats going on under the ice.

For in-depth learning and more handy features of signpost you can find this WWDC video very useful:

Measuring Performance Using Logging — WWDC 2018 — Videos — Apple Developer

--

--

Amit Nadir

Staff Mobile Developer @Ping Identity. Developing mobile apps & SDK with Swift, Objective-C and Android apps with Java and Kotlin.