1. 主线程卡顿现象识别

主线程卡顿是一系列可被用户、系统或工具感知的异常行为的总称。准确的现象识别是后续数据采集与原因定位的前提。根据异常表现的严重程度与触发条件,可将主线程卡顿分为三类:ANR 弹窗、掉帧感知、用户操作无响应。下面通过一张故障树梳理三者之间的关系与判别路径。

主线程卡顿现象识别故障树 主线程卡顿现象 ANR 弹窗 掉帧感知 操作无响应 系统弹窗提示 “应用无响应” 需等待或关闭 界面滑动/动画卡顿 帧率明显下掉 丢帧率 > 0.1% 用户点击无反馈 按钮、滚动、输入 均无即时响应 系统级事件 Trace 可观测 综合体验感知

1.1 现象分类与识别依据

现象类别触发条件用户感知系统输出识别证据
ANR 弹窗主线程阻塞超过 5s(前台)/ 10s(广播)/ 60s(输入)屏幕出现“应用无响应”对话框,无法操作logcat 输出 ANR in xxx + traces 文件dumpsys dropbox 中 anr 记录
掉帧感知单帧绘制时间 > 16.67ms(60fps)或 > 8.33ms(120fps)滑动/动画出现跳跃、延迟,视觉不流畅Choreographer 跳帧日志,GPU 渲染时间线Perfetto 中 SurfaceFlinger 帧间隔 > 1 vsync
操作无响应主线程事件队列长时间排队,未触发 ANR 超时点击/触摸后界面 > 200ms 无任何反馈TouchEvent 分发起始延迟长,InputReader 记录Perfetto 中 InputTransport 耗时 > 200ms

关键判断规则:

  • 看到系统弹框 → 直接定位为 ANR 现象。
  • 滑动时有肉眼可察卡顿但无弹框 → 优先视为掉帧现象,需进一步获取帧渲染数据。
  • 用户反复点击后无反应,且 logcat 无 ANR 标识 → 归为操作无响应,注意与线程死锁或消息队列阻塞有关。

1.2 现象识别实操:命令行与日志验证

当收到用户反馈或监控告警后,先通过以下快速命令确认现象归属。

# 检查最近 ANR 记录
adb shell dumpsys dropbox --print | grep -A 20 "ANR"

# 检查当前是否有 pending 的 ANR
adb shell dumpsys activity processes | grep "waitingForTransition|anr"

# 实时观察帧率(需要设备支持)
adb shell dumpsys gfxinfo [package] framestats

# 抓取主线程消息队列时间分布
adb shell dumpsys activity messages | grep "MessageQueue idleTime"

经验提示:

现象识别阶段不要急于分析源码。先通过系统日志和用户复现路径确认是哪种卡顿现象,不同现象对应的 Perfetto 采集配置(后续章节)会截然不同。例如 ANR 需要抓取系统全局 traces 和进程 CPU 状态,而掉帧感知更适合采集 GPU 渲染 Pipeline。

1.3 从现象到采集的决策矩阵

识别出具体现象后,可以快速决定下一步采集方案。以下矩阵帮助你在现象识别完成后直接跳到对应的数据采集章节。

识别结果推荐采集切入点(章节)关键 Perfetto 数据源
ANR 弹窗第 3 章 · 系统 ANR traces 抓取android.anr / kernel.sched / process.cpu
掉帧感知第 5 章 · 帧渲染 Pipeline 追踪gpu.renderstage / composition / SurfaceFlinger
操作无响应第 7 章 · 主线程 MessageQueue 分析android.choreographer / input / binder

常见误判:

  • 将系统 GC 引起的瞬时掉帧误判为 ANR(可通过 Perfetto 中 Java Heap 区确认)。
  • 将网络请求超时导致的表象无响应误判为卡顿(需区分主线程是否在等待锁)。
  • 将低端机性能不足导致的常态掉帧当作异常(需与环境基线对比)。

本章完成了卡顿现象的识别与分类。接下来按照上述决策矩阵,选择对应的数据采集章节,进入后续的量化分析阶段。