Question 2
Using Instruments effectively
An app feels slow, but the cause isn’t obvious. How do you use Instruments to narrow it down, and which templates do you usually start with?
Follow-ups
- Time Profiler vs Allocations vs Leaks vs Memory Graph?
- What patterns do you look for first?
Answer outline
Match the symptom to the right template first — then drill down into the patterns within it.
- 1.CPU or UI hitches → Time Profiler: filter to Main Thread, find the hottest symbols and call trees. Red flags: sync I/O, JSON decode, and regex in hot paths.
- 2.Memory climbing → Allocations: repeat an action and watch net growth. Unbounded growth points to caches without eviction or retained closures. Use Generations to isolate what survives an operation.
- 3.Suspected leaks → Leaks: finds abandoned heap allocations and classic leak paths.
- 4.Retain cycles or orphaned view controllers → Memory Graph: inspect reference chains — delegate strong refs, closure captures — directly in Xcode.
Principles
- Profile on a physical device in Release mode with realistic data — Debug builds and empty databases lie.
- Take a baseline trace, change one thing, then compare before and after.
- Don’t chase tiny wins like
objc_msgSenduntil the big bottlenecks are gone.
os_signpost pairs with Points of Interest — see your phases correlated in the timeline.
Mark a region in Instruments
import os.signpost
let log = OSLog(subsystem: "com.app", category: "Feed")
os_signpost(.begin, log: log, name: "LoadPage")
defer { os_signpost(.end, log: log, name: "LoadPage") }
Follow-up angles
- Energy template when battery heat matters — correlates CPU, location, and network usage together.
- System Trace for thread scheduling and priority inversion when background tasks block UI.