如何用 Systrace 等工具深入分析响应慢问题

45 阅读3分钟

这篇文章是 Android 响应速度优化的进阶内容,主要讲解如何用 Systrace 等工具深入分析响应慢问题,并介绍启动优化的实用技巧。用大白话总结如下:

一、进程状态:CPU 如何 “安排” 任务?

在 Systrace 中,进程任务有三种状态(看颜色):

  1. 绿色 Running:任务正在 CPU 核心上执行(比如炒菜时正在翻炒)。

    • 若 Running 时间过长,可能是代码逻辑复杂(如加载大图)或跑在小核心(小马拉大车)。
  2. 蓝色 Runnable:任务在排队等 CPU 资源(像排队等炒菜锅)。

    • 若 Runnable 多,说明 CPU 太忙(比如多个进程同时抢资源)。
  3. 白色 Sleep:任务在 “睡觉”,等消息或其他资源(如等食材准备好)。

    • 常见于等待 Binder 通信(如 App 等系统服务返回数据)或 IO 操作(读磁盘文件)。

二、TraceView:给代码 “拍慢动作”

  • 作用:抓取应用启动时的函数调用耗时,定位具体哪段代码拖慢速度。

  • 使用方法

    bash

    # 冷启动并抓取TraceView(替换包名)
    adb shell am start -n com.example/.SplashActivity --start-profiler trace.trace  
    sleep 10 && adb shell am profile stop com.example  
    adb pull trace.trace  
    
  • 缺点:采样太细会影响性能,时间数据不准,但能定位函数调用栈(如发现某个三方库初始化耗时)。

三、SimplePerf:更全面的 “监控器”

  • 比 TraceView 强在哪:能同时抓取 Java 和 Native 层的堆栈(比如查看 C++ 代码是否耗时)。

  • 用法

    bash

    python app_profiler.py -p com.example  # 启动App后手动结束  
    python report_html.py  # 生成HTML报告  
    
  • 适用场景:分析启动时的底层瓶颈(如系统库调用耗时)。

四、组件启动时机:谁在拖慢启动速度?

  1. Service/BroadcastReceiver

    • 代码中启动 Service 时,实际是向 Handler 发送消息,排队执行(比如点击按钮后 Service 可能几秒后才启动)。
  2. ContentProvider

    • 在 Application.onCreate 之前就初始化,若三方库用 ContentProvider 初始化(如 Firebase),会堆积启动耗时(比如 50 个 ContentProvider 可能拖慢 20ms)。
  3. 优化方案

    • 用 AppStartup 库合并 ContentProvider,延迟非必要初始化(如把 “微信登录” 库延迟到用户点击时再启动)。

五、启动优化技巧:让 App 启动更快

  1. IdleHandler:空闲时 “补作业”

    • 在 MessageQueue 没任务时执行非紧急任务(如加载广告图片),避免阻塞主线程。
    • 例子:首页列表加载完后,用 idleHandler 通知系统 “启动完成”(activity.reportFullyDrawn()),让系统记录真实启动时间。
  2. AppStartup 库:管理三方库启动顺序

    • 解决问题:多个三方库用 ContentProvider 初始化,导致启动时一堆任务并行执行。
    • 效果:若有 50 + 个 ContentProvider,可减少 20ms 以内的启动耗时。

六、总结:响应慢分析的核心思路

  1. 看状态:用 Systrace 看进程是在 Running(自己慢)、Runnable(CPU 忙)还是 Sleep(等资源)。
  2. 抓细节:用 TraceView/SimplePerf 定位具体函数,用 AppStartup 优化三方库初始化。
  3. 调时机:用 IdleHandler 延迟非必要任务,让启动时主线程优先处理关键功能。