axiom-concurrency-profiling
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseConcurrency Profiling — Instruments Workflows
并发性能分析 — Instruments 工作流
Profile and optimize Swift async/await code using Instruments.
使用Instruments分析并优化Swift async/await代码。
When to Use
适用场景
✅ Use when:
- UI stutters during async operations
- Suspecting actor contention
- Tasks queued but not executing
- Main thread blocked during async work
- Need to visualize task execution flow
❌ Don't use when:
- Issue is pure CPU performance (use Time Profiler)
- Memory issues unrelated to concurrency (use Allocations)
- Haven't confirmed concurrency is the bottleneck
✅ 适合使用的情况:
- 异步操作期间UI出现卡顿
- 怀疑存在actor竞争问题
- 任务已排队但未执行
- 异步工作期间主线程被阻塞
- 需要可视化任务执行流程
❌ 不适合使用的情况:
- 问题属于纯CPU性能问题(使用Time Profiler工具)
- 与并发无关的内存问题(使用Allocations工具)
- 尚未确认并发是性能瓶颈
Swift Concurrency Template
Swift Concurrency模板
What It Shows
展示内容
| Track | Information |
|---|---|
| Swift Tasks | Task lifetimes, parent-child relationships |
| Swift Actors | Actor access, contention visualization |
| Thread States | Blocked vs running vs suspended |
| 追踪项 | 信息说明 |
|---|---|
| Swift Tasks | 任务生命周期、父子关系 |
| Swift Actors | Actor访问、竞争可视化 |
| Thread States | 阻塞、运行、挂起状态 |
Statistics
统计数据
- Running Tasks: Tasks currently executing
- Alive Tasks: Tasks present at a point in time
- Total Tasks: Cumulative count created
- Running Tasks:当前正在执行的任务
- Alive Tasks:某一时刻存在的任务
- Total Tasks:累计创建的任务总数
Color Coding
颜色编码
- Blue: Task executing
- Red: Task waiting (contention)
- Gray: Task suspended (awaiting)
- 蓝色:任务正在执行
- 红色:任务等待中(竞争状态)
- 灰色:任务已挂起(等待await)
Workflow 1: Diagnose Main Thread Blocking
工作流1:排查主线程阻塞问题
Symptom: UI freezes, main thread timeline full
- Profile with Swift Concurrency template
- Look at main thread → "Swift Tasks" lane
- Find long blue bars (task executing on main)
- Check if work could be offloaded
Solution patterns:
swift
// ❌ Heavy work on MainActor
@MainActor
class ViewModel: ObservableObject {
func process() {
let result = heavyComputation() // Blocks UI
self.data = result
}
}
// ✅ Offload heavy work
@MainActor
class ViewModel: ObservableObject {
func process() async {
let result = await Task.detached {
heavyComputation()
}.value
self.data = result
}
}症状:UI冻结,主线程时间线被占满
- 使用Swift Concurrency模板进行性能分析
- 查看主线程 → "Swift Tasks" 通道
- 寻找较长的蓝色条(主线程上执行的任务)
- 检查该工作是否可以被卸载到其他线程
解决方案示例:
swift
// ❌ 在MainActor上执行繁重工作
@MainActor
class ViewModel: ObservableObject {
func process() {
let result = heavyComputation() // 阻塞UI
self.data = result
}
}
// ✅ 卸载繁重工作
@MainActor
class ViewModel: ObservableObject {
func process() async {
let result = await Task.detached {
heavyComputation()
}.value
self.data = result
}
}Workflow 2: Find Actor Contention
工作流2:排查Actor竞争问题
Symptom: Tasks serializing unexpectedly, parallel work running sequentially
- Enable "Swift Actors" instrument
- Look for serialized access patterns
- Red = waiting, Blue = executing
- High red:blue ratio = contention problem
Solution patterns:
swift
// ❌ All work serialized through actor
actor DataProcessor {
func process(_ data: Data) -> Result {
heavyProcessing(data) // All callers wait
}
}
// ✅ Mark heavy work as nonisolated
actor DataProcessor {
nonisolated func process(_ data: Data) -> Result {
heavyProcessing(data) // Runs in parallel
}
func storeResult(_ result: Result) {
// Only actor state access serialized
}
}More fixes:
- Split actor into multiple (domain separation)
- Use Mutex for hot paths (faster than actor hop)
- Reduce actor scope (fewer isolated properties)
症状:任务意外串行化,并行工作按顺序执行
- 启用"Swift Actors"工具
- 查找串行访问模式
- 红色=等待,蓝色=执行
- 红/蓝比例高=存在竞争问题
解决方案示例:
swift
// ❌ 所有工作通过Actor串行执行
actor DataProcessor {
func process(_ data: Data) -> Result {
heavyProcessing(data) // 所有调用者都需等待
}
}
// ✅ 将繁重工作标记为nonisolated
actor DataProcessor {
nonisolated func process(_ data: Data) -> Result {
heavyProcessing(data) // 并行执行
}
func storeResult(_ result: Result) {
// 仅Actor状态访问会被串行化
}
}更多修复方案:
- 将单个Actor拆分为多个(按领域划分)
- 在热点路径使用Mutex(比Actor切换更快)
- 缩小Actor作用范围(减少隔离属性)
Workflow 3: Thread Pool Exhaustion
工作流3:排查线程池耗尽问题
Symptom: Tasks queued but not executing, gaps in task execution
Cause: Blocking calls exhaust cooperative pool
- Look for gaps in task execution across all threads
- Check for blocking primitives
- Replace with async equivalents
Common culprits:
swift
// ❌ Blocks cooperative thread
Task {
semaphore.wait() // NEVER do this
// ...
semaphore.signal()
}
// ❌ Synchronous file I/O in async context
Task {
let data = Data(contentsOf: fileURL) // Blocks
}
// ✅ Use async APIs
Task {
let (data, _) = try await URLSession.shared.data(from: fileURL)
}Debug flag:
SWIFT_CONCURRENCY_COOPERATIVE_THREAD_BOUNDS=1Detects unsafe blocking in async context.
症状:任务已排队但未执行,任务执行存在间隙
原因:阻塞调用耗尽了协作线程池
- 查看所有线程的任务执行间隙
- 检查是否存在阻塞原语
- 替换为异步等效实现
常见问题代码:
swift
// ❌ 阻塞协作线程
Task {
semaphore.wait() // 绝对不要这样做
// ...
semaphore.signal()
}
// ❌ 在异步上下文执行同步文件I/O
Task {
let data = Data(contentsOf: fileURL) // 阻塞线程
}
// ✅ 使用异步API
Task {
let (data, _) = try await URLSession.shared.data(from: fileURL)
}调试标志:
SWIFT_CONCURRENCY_COOPERATIVE_THREAD_BOUNDS=1用于检测异步上下文中的不安全阻塞操作。
Workflow 4: Priority Inversion
工作流4:排查优先级反转问题
Symptom: High-priority task waits for low-priority
- Inspect task priorities in Instruments
- Follow wait chains
- Ensure critical paths use appropriate priority
swift
// ✅ Explicit priority for critical work
Task(priority: .userInitiated) {
await criticalUIUpdate()
}症状:高优先级任务等待低优先级任务
- 在Instruments中检查任务优先级
- 追踪等待链
- 确保关键路径使用合适的优先级
swift
// ✅ 为关键工作设置明确优先级
Task(priority: .userInitiated) {
await criticalUIUpdate()
}Thread Pool Model
线程池模型
Swift uses a cooperative thread pool matching CPU core count:
| Aspect | GCD | Swift Concurrency |
|---|---|---|
| Threads | Grows unbounded | Fixed to core count |
| Blocking | Creates new threads | Suspends, frees thread |
| Dependencies | Hidden | Runtime-tracked |
| Context switch | Full kernel switch | Lightweight continuation |
Why blocking is catastrophic:
- Each blocked thread holds memory + kernel structures
- Limited threads means blocked = no progress
- Pool exhaustion deadlocks the app
Swift使用协作线程池,其大小与CPU核心数匹配:
| 特性 | GCD | Swift Concurrency |
|---|---|---|
| 线程 | 无限制增长 | 固定为核心数 |
| 阻塞处理 | 创建新线程 | 挂起任务,释放线程 |
| 依赖关系 | 隐藏 | 运行时追踪 |
| 上下文切换 | 完整内核切换 | 轻量级续体切换 |
阻塞操作的严重影响:
- 每个阻塞线程会占用内存和内核结构
- 线程数量有限,阻塞意味着无法推进工作
- 线程池耗尽会导致应用死锁
Quick Checks (Before Profiling)
预检查(分析前)
Run these checks first:
-
Is work actually async?
- Look for suspension points ()
await - Sync code in async function still blocks
- Look for suspension points (
-
Holding locks across await?swift
// ❌ Deadlock risk mutex.withLock { await something() // Never! } -
Tasks in tight loops?swift
// ❌ Overhead may exceed benefit for item in items { Task { process(item) } } // ✅ Structured concurrency await withTaskGroup(of: Void.self) { group in for item in items { group.addTask { process(item) } } } -
DispatchSemaphore in async context?
- Always unsafe — use instead
withCheckedContinuation
- Always unsafe — use
先执行以下检查:
-
工作是否真的是异步的?
- 查找挂起点()
await - 异步函数中的同步代码仍会阻塞线程
- 查找挂起点(
-
在await期间持有锁?swift
// ❌ 存在死锁风险 mutex.withLock { await something() // 绝对不要这样做! } -
在循环中创建大量任务?swift
// ❌ 开销可能超过收益 for item in items { Task { process(item) } } // ✅ 使用结构化并发 await withTaskGroup(of: Void.self) { group in for item in items { group.addTask { process(item) } } } -
在异步上下文使用DispatchSemaphore?
- 绝对不安全 — 改用
withCheckedContinuation
- 绝对不安全 — 改用
Common Issues Summary
常见问题汇总
| Issue | Symptom in Instruments | Fix |
|---|---|---|
| MainActor overload | Long blue bars on main | |
| Actor contention | High red:blue ratio | Split actors, use |
| Thread exhaustion | Gaps in all threads | Remove blocking calls |
| Priority inversion | High-pri waits for low-pri | Check task priorities |
| Too many tasks | Task creation overhead | Use task groups |
| 问题 | Instruments中的症状 | 修复方案 |
|---|---|---|
| MainActor过载 | 主线程上存在长蓝色条 | |
| Actor竞争 | 红/蓝比例高 | 拆分Actor,使用 |
| 线程池耗尽 | 所有线程存在执行间隙 | 移除阻塞调用 |
| 优先级反转 | 高优先级任务等待低优先级任务 | 检查任务优先级 |
| 任务数量过多 | 任务创建开销大 | 使用任务组 |
Safe vs Unsafe Primitives
安全与不安全原语
Safe with cooperative pool:
- , actors, task groups
await - ,
os_unfair_lock(short critical sections)NSLock - (iOS 18+)
Mutex
Unsafe (violate forward progress):
DispatchSemaphore.wait()pthread_cond_wait- Sync file/network I/O
- in Task
Thread.sleep()
适用于协作线程池的安全原语:
- , actors, 任务组
await - ,
os_unfair_lock(短临界区)NSLock - (iOS 18+)
Mutex
不安全原语(违反向前推进原则):
DispatchSemaphore.wait()pthread_cond_wait- 同步文件/网络I/O
- 在Task中使用
Thread.sleep()
Resources
参考资源
WWDC: 2022-110350, 2021-10254
Docs: /xcode/improving-app-responsiveness
Skills: axiom-swift-concurrency, axiom-performance-profiling, axiom-synchronization
WWDC:2022-110350, 2021-10254
文档:/xcode/improving-app-responsiveness
技能:axiom-swift-concurrency, axiom-performance-profiling, axiom-synchronization