5-24.【性能分析与优化】在 Instruments 中,如何判断一个性能问题是 ARC、派发、算法、I/O 中的哪一类?

2 阅读2分钟

目标:10 分钟内判断问题属于 ARC / 派发 / 算法 / I/O 中哪一类


一、先给你一张「症状 → 根因」速查表(很实用)

Instruments 症状最可能类别
swift_retain / swift_release 占比高ARC
objc_msgSend / witness table派发
CPU 高、调用栈很“干净”算法
CPU 不高但卡I/O / 等待 / 调度
Allocation rate 高 + 生命周期短ARC / Boxing
单次调用耗时长但不频繁I/O / 系统调用

先有这个全局印象,下面是具体如何确认


二、Step-by-Step 诊断流程(真实工作流)

Step 1️⃣ 只看 Time Profiler:CPU 在干嘛?

先不展开你自己的代码,看 Top Symbols

🧠 如果你看到的是这些:

🔴 ARC 型

swift_retain
swift_release
swift_allocObject

👉 先判定:ARC 问题

下一步验证:

  • 切到 Allocations

  • 看是否有:

    • 大量短命对象
    • existential container
    • closure

🔴 派发型

objc_msgSend
swift_dynamicCast
swift_witness_table

👉 派发问题

含义:

  • 协议存在类型
  • 非 final class
  • @objc / dynamic
  • 泛型未特化

🔴 算法型

你看到的栈是:

myFunction
 └── helper
     └── loop
         └── math / array access
  • 没有 runtime
  • 没有 retain/release
  • 栈很“干净”

👉 算法 / 数据结构问题


🔴 I/O / 等待型

  • CPU 不高

  • App 仍然卡顿

  • Time Profiler 显示:

    • mach_msg_trap
    • pthread_cond_wait
    • dispatch_sync

👉 I/O / 锁 / 主线程阻塞


三、第二确认:Allocations 怎么说?

Allocations 是验证器

ARC / 派发相关

Allocations 现象说明
很多小对象boxing / closure
生命周期极短ARC 热点
分配与 UI 帧同步SwiftUI / body

算法相关

现象说明
分配很少纯计算
CPU 高算法复杂度 / cache miss
单次调用耗时稳定O(n) / O(n²)

I/O 相关

现象说明
几乎没分配等待系统
CPU 低被阻塞
时间线有大块空白sleep / wait

四、第三确认:对照“反事实假设”

这是我个人最常用的技巧。

假设 1:如果我把代码改成纯 struct + 泛型,会怎样?

  • 如果 ARC / 派发热点消失 → 原因确认
  • 如果几乎没变化 → 算法 or I/O

假设 2:如果我把数据量减半,会怎样?

  • 时间 ≈ 1/2 → O(n)
  • 时间 ≈ 1/4 → O(n²)
  • 时间几乎不变 → ARC / 派发 / I/O

假设 3:如果我关掉网络 / 磁盘?

  • 问题消失 → I/O
  • 问题仍在 → 纯 CPU / ARC

五、四类问题的「最终确认信号」

🟠 ARC(内存管理)

  • swift_retain / release 排前

  • Allocations:短命对象

  • closure / protocol existential

  • 优化方式:

    • 泛型
    • inout
    • 减少逃逸

🟣 派发(Dispatch)

  • objc_msgSend / witness table

  • 协议类型 / open class

  • 优化方式:

    • final
    • 泛型
    • private / internal
    • @inlinable

🔵 算法(Algorithm)

  • CPU 高

  • 栈干净

  • 分配少

  • 优化方式:

    • 改复杂度
    • 数据结构
    • cache locality

🟢 I/O / 等待

  • CPU 低

  • 主线程阻塞

  • dispatch / mach

  • 优化方式:

    • 异步
    • 批量
    • 预取

六、最终心法(非常重要)

Instruments 从来不会直接告诉你“这是 ARC 问题”
它只会告诉你:

  • CPU 在 runtime
  • 还是在你的代码
  • 还是在等系统

你要做的是:

从“运行时在忙什么”,反推出“代码结构在逼它干什么”。