Which Instruments templates do you reach for, how do you read a Time Profiler trace, and where can a sampling profiler mislead you?
Predict first
A screen freezes for a second while it waits on a lock held by another thread. Which tool finds it?
// A: Time Profiler on the main thread, which shows the lock wait as CPU time
// B: System Trace or the Hangs instrument, which show the main thread blocked
// C: Leaks
- A
- B
- C
Mental model. Time Profiler is a camera taking a photo of every thread each millisecond: great for finding where people stand most, useless for people who are asleep in the queue.
Pick the template from the symptom. Time Profiler answers “where is the CPU time going”: it samples every thread’s call stack at a fixed interval (about a millisecond by default) and aggregates the samples, so the functions with the most samples are the ones that ran longest. Read it with the call tree inverted (heaviest leaf functions first), filter to the main thread when the complaint is a hang, and separate self time (in this function) from total time (including callees). System Trace shows what threads were doing: running, runnable but waiting for a core, or blocked on a lock, I/O or a queue, which finds problems a CPU profile cannot (waiting is not CPU). Hangs and Animation Hitches find blocked main threads and missed frames, the SwiftUI template shows view body updates, Allocations and Leaks follow memory (Q160), and the Power Profiler and Energy tools show energy on a device.
A sampling profiler is a statistical tool, so know its limits. Work that is shorter than the sampling interval can be missed or under-counted, a thread that is waiting uses no CPU and so does not show in Time Profiler at all (use System Trace), and the numbers describe this build, this device and this run. Profile a Release build on a device, with symbols so the stacks have names, and record the scenario several times. When a profile and the user’s experience disagree, trust the experience and look in a different dimension.
A blocked thread uses no CPU, so a sampling CPU profile hardly sees it. The thread-state view shows the wait.
| Question it answers | Blind spot | |
|---|---|---|
| Time Profiler | which code uses the CPU | waiting; very short work between samples |
| System Trace | what threads ran, waited or were blocked on | needs more interpretation, bigger traces |
| Hangs and Animation Hitches | where the main thread stalled, which frames were late | tell you that and when, not always why |
| Allocations and Leaks | what memory grew and who allocated it | not CPU or energy |
| SwiftUI instrument | which view bodies ran and how often | only SwiftUI work |
Common traps
- Looking only at total time at the top of the tree. Everything is under
main; invert the tree or hide system libraries to see your own hot spots. - Using Time Profiler for a slow screen that is waiting on a lock or network. Waiting is not CPU; use System Trace or the Hangs instrument.
They might follow up with
- What is the difference between self and total time? Self is time spent in the function’s own code; total includes everything it called.
- Why symbolicate? Without symbols the stack shows addresses; with them you can see which function is hot.
Related questions
- 21.2.2 How do signposts and Points of Interest work, and how do you turn a measurement into an XCTest performance…
- 21.1.1 How do you approach a performance problem, and which kinds of problem are there?
- 3.7.3 How do you use Instruments’ Allocations, Leaks and VM Tracker to track a memory problem?
- 9.7.1 What is a hitch versus a hang, how does ProMotion change the budget, and how do you measure and fix them?
How do signposts and Points of Interest work, and how do you turn a… →