Systrace 工具分析卡顿的原理

163 阅读3分钟

这篇文章主要讲安卓手机卡顿的原理,以及如何用 Systrace 工具分析流畅度问题,用大白话总结如下:

一、什么是卡顿?用户和开发者的理解不同

  • 用户眼中的卡顿:滑动列表时画面卡住、应用启动慢、点击没反应、动画不连贯等。

  • 开发者的分类

    • 流畅度问题:滑动掉帧、动画卡顿(比如刷抖音时画面一顿一顿)。

    • 响应速度问题:点击按钮后很久才反应(比如打开微信慢)。

    • 稳定性问题:操作后闪退或卡死(比如玩游戏时突然黑屏)。

核心原因:这三类问题本质都是主线程处理任务超时,就像工厂流水线堵车,导致画面更新慢。

二、一帧画面是怎么 “画” 出来的?卡顿如何发生?

手机要显示一帧画面,流程像工厂流水线:

  1. 闹钟响(Vsync 信号) :屏幕刷新前会发一个 “开始画画” 的信号(约 16.6ms 一次,对应 60fps)。

  2. 主线程干活:处理用户输入(比如滑动)、动画计算、界面布局(量尺寸、摆位置)。

  3. 渲染线程画图:用 GPU 把界面画到 “画布”(Buffer)上。

  4. 拼图画(SurfaceFlinger) :把所有 App 的 “画布” 合成一张图,交给屏幕显示。

卡顿怎么来的?
如果任何一步超时(比如主线程算布局太慢),就会导致:

  • 下一帧没画完,屏幕只能重复显示上一帧(画面卡住)。
  • 就像做饭时切菜太慢,导致上菜延迟,客人等得不耐烦。

三、关键机制:为什么会超时?系统怎么 “补救”?

  1. 主线程的 “快递系统”(Message 机制)
    主线程靠 Handler/Looper/MessageQueue 传递任务,像快递员按顺序送包裹。如果某个任务(比如加载大图)耗时太长,后面的任务都得排队,导致整体卡顿。

  2. 屏幕刷新的 “闹钟”(Vsync)
    屏幕每秒刷新 60 次(60Hz),对应每 16.6ms 需要一帧画面。如果 App 在 16.6ms 内没画完,就会掉帧(fps 降低),比如从 60fps 降到 40fps,用户就会感觉卡。

  3. 画布不够用?三 Buffer 救场!

    • 双 Buffer:只有 2 个 “画布”,如果 App 画画慢,SurfaceFlinger 拿不到新画布,就会重复显示旧画面(卡顿)。
    • 三 Buffer:有 3 个画布轮转,即使某一步慢了,也能暂时用多余的画布救急,减少卡顿次数(但会多占内存)。
  4. 用户操作的 “传递链”(Input 流程)
    手指滑动时,InputReader 读取触摸事件,InputDispatcher 分发到 App,主线程被唤醒处理。如果这个链条任何一环卡住(比如系统忙不过来),就会导致滑动不跟手。

四、如何用 Systrace 抓出卡顿元凶?

Systrace 是个 “监控摄像头”,能记录整个画面渲染流程:

  • 看主线程是否被耗时任务阻塞(比如 GC 垃圾回收、复杂布局)。

  • 看渲染线程是否卡在读 Buffer 或 GPU 渲染慢。

  • 看 SurfaceFlinger 合成是否超时,或 BufferQueue 里的画布是否不够用。

举个例子:如果 Systrace 显示某一帧的主线程处理用了 25ms(超过 16.6ms),就说明这一帧可能导致卡顿,需要优化主线程任务(比如把耗时操作移到后台线程)。

五、总结:卡顿就是 “流水线堵车”,Systrace 是 “交通警察”

  • 卡顿本质:App 渲染一帧的时间超过了屏幕刷新周期,导致画面更新不及时。

  • 分析思路:用 Systrace 查看流水线哪一步堵了(主线程 / 渲染线程 / GPU/SurfaceFlinger),然后针对性优化(比如减少主线程计算、增加 Buffer 数量、优化 GPU 渲染)。

这篇文章是系列第一篇,后续会教具体的实战分析案例,帮助开发者通过 Systrace 解决实际卡顿问题。