← All shorts
74iOS 15+2 min read

os_signpost and Instruments for Real Performance Data

os_signpost emits custom timeline events Instruments can visualise, turning guesswork about slow code into real data.

print-based timing tells you one number in the console, on one run, with no way to correlate it against what else the app or system was doing at that moment — no thread state, no overlapping work, no visual timeline.

#The old way

import Foundation

func loadFeed() {
    let start = Date()
    performExpensiveDecode()
    let elapsed = Date().timeIntervalSince(start)
    print("loadFeed took \(elapsed)s")
}

#The new way

import os

let logger = Logger(subsystem: "com.example.app", category: "feed")
let signposter = OSSignposter(logger: logger)

func loadFeed() {
    let state = signposter.beginInterval("Load Feed")
    performExpensiveDecode()
    signposter.endInterval("Load Feed", state)
}

#Why it matters

  • Signpost intervals show up as named ranges directly on Instruments' timeline, alongside CPU, memory, and thread activity for the same window
  • OSSignposter is built on the unified logging system (Logger), so the same category and subsystem you use for regular logs group your performance data too
  • Signposts cost very little at runtime and are safe to leave in release builds — they're inert unless a profiling tool is actually attached
  • Nesting intervals lets you see which part of a slow operation is actually expensive, instead of one aggregate number for the whole function

#Gotcha

Signposts only tell a story if attached with Instruments (or a custom os_signpost handler) while the code runs — nothing shows up from a debug build the phone was just carrying around normally, which trips people up expecting some form of always-on logging. Interval names passed to beginInterval/endInterval must match exactly for Instruments to pair them into a single range; a typo produces two orphaned point events instead of one interval. The exact OSSignposter method signatures have shifted slightly since introduction, so confirm parameter labels against current documentation before wiring this into a shared logging helper.

instrumentsperformanceos_signpost

Related shorts