Administrator
发布于 2026-08-25 / 35 阅读
0
0

系列文章《Android 工程师的 100 篇进阶笔记》第 65 篇:Systrace 与 Perfetto:从 CSV 到万帧分析的进阶之路

上一篇讲了 MVI 架构,切换到性能分析工具——Systrace 与 Perfetto。每个 Android 工程师都该会 Systrace 抓问题,但 Perfetto 是更强的下一代工具。这篇把它们一起讲清楚。

Systrace 是什么

Systrace 是 Android 自带的性能分析工具,记录设备在指定时间段内所有进程、线程的活动:

[Systrace 输出样例简化]
process: com.example.app
  线程 main:
    Task: onCreate           0ms -- 50ms
    Task: setContentView     50ms -- 200ms
    Task: user input handled  200ms -- 250ms
    [(等待)]                250ms -- 800ms <- 卡!

底层数据源:Linux kernel ftrace(ftrace 是 Linux 内核 trace 工具)。Android 在 ftrace 上包了一层。

命令行抓 trace

# 1. 确保 adb 调试就绪
adb devices

# 2. 进入开发者选项,打开"USB 调试"和"跟踪"选项

# 3. 监控 5 秒,操作你的 App
adb shell atrace --async_start -t 10 view gfx input webview am wm res dalvik

# 4. 或者直接抓 + 拉取
adb shell atrace --async_dump > /tmp/mytrace.html

# 5. 打开 mytrace.html 看图
open /tmp/mytrace.html

参数说明:

参数

含义

-t N

抓 N 秒

view

View 体系(测量/布局/绘制)

gfx

RenderThread 渲染

input

输入事件

am

ActivityManager 调用

wm

WindowManager 调用

res

资源加载

dalvik

Dalvik/ART 虚拟机

注意:-async_start 是后台运行不阻塞,后台启动后再操作 App,结束时 atrace --async_stop。

Perfetto 比 Systrace 强在哪里

Perfetto 是 Google 主导的下一代 tracing 工具,整合了:

  • Systrace(系统级)

  • ftrace(内核)

  • atrace(Android)

  • Chrome trace format

  • 自定义事件

维度

Systrace

Perfetto

输出格式

HTML

protobuf,能流式处理

数据源

单一

多源、可自定义

数据量

小(10秒一段)

大(连续小时)

UI 工具

浏览器

web UI 或专属 viewer

自定义事件

ATRACE_BEGIN

通过 Trace 库 + protobuffer

适用版本

所有

Android 10+ 优化最好

Perfetto 命令行使用

# 1. 启动录制
adb shell perfetto \
    --out /data/misc/perfetto-traces/trace.perfetto-trace \
    --time_in_state 10 \
    --async

# 2. 抓 10 秒后停止
sleep 10
adb shell kill -INT $(pidof perfetto)

# 3. 拉取
adb pull /data/misc/perfetto-traces/trace.perfetto-trace

# 4. 在 https://ui.perfetto.dev 上传查看

指定配置(录制自定义数据):

cat > config.txt << 'EOF'
duration_ms: 10000
buffers: {
    size_kb: 2048
    fill_policy: DISCARD
}
data_sources: {
    config {
        name: "linux.ftrace"
        ftrace_config {
            ftrace_events: "sched"
            ftrace_events: "task_rename"
        }
    }
}
data_sources: {
    config {
        name: "android.process_stat"
    }
}
data_sources: {
    config {
        name: "android.surfaceflinger"
    }
}
EOF

adb push config.txt /data/local/tmp/trace_config.txt
adb shell perfetto -c /data/local/tmp/trace_config.txt \
    --out /data/misc/perfetto-traces/trace.perfetto-trace

更详细的配置可见 Perfetto 文档。

在代码里插桩自定义事件

Systrace(ATRACE)

// Native
ATRACE_BEGIN("MyModule::init");
doSomething();
ATRACE_END();

// Java
import android.os.Trace;
Trace.beginSection("LoadUser");
loadUser();
Trace.endSection();

Perfetto(更强大)

// 1. 添加依赖
dependencies {
    implementation("androidx.tracing:tracing-perfetto:1.0.0")
}

// 2. 注册自定义事件
import androidx.tracing.perfetto.Tracing

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()

        if (BuildConfig.DEBUG) {
            Tracing.enable()
        }
    }
}

// 3. 业务里打点
Tracing.trace("MySection", block = { ... })

// 协程集成
Tracing.traceCoroutine("MyNetworkCall") {
    api.fetchData()
}

自定义事件能在 Perfetto UI 上专门过滤。

分析常见问题模式

1. 启动慢

打开启动 trace,重点看:

[zygote 启动]                 0ms -- 200ms
[classloader 加载 classes.dex] 200ms -- 800ms  <- 关注
[Application.onCreate]          800ms -- 1200ms
[Activity.onCreate]             1200ms -- 1500ms
[第一次 measure/layout]         1500ms -- 2500ms <- 关注

常见优化点:

  • classloader 加载时间 → 用 Baseline Profiles 提前 AOT

  • onCreate 耗时 → 移到工作线程

  • 第一次 measure/layout → 拆解布局、减少嵌套

2. 卡顿

滑动列表卡顿时,每个 frame 应该 16ms(60Hz)或者 8.3ms(120Hz):

[vsync 0]                      0ms
[Choreographer.doFrame 0]      0.5ms
[measure]                      0.5ms --  4ms
[layout]                       4ms --  6ms
[draw]                         6ms -- 12ms
[swap buffers]                 12ms -- 15ms

[vsync 1]                      16.6ms
[Choreographer.doFrame 1]      17.1ms
[measure]                      17ms -- 25ms  <- 拖了 5ms
[layout]                       25ms -- 30ms
[draw]                         30ms -- 50ms   <- 掉帧!

Perfetto UI 上能看每个 vsync 是不是 16ms 间隔,红色就是掉帧。

3. ANR

ANR 时 trace 关键看:

  • 主线程 task 持续时间

  • Binder call 阻塞时间

  • 主线程 sleep/wait

Binder 阻塞最常见,主线程调用其它服务被卡。常见的有:

  • ContentProvider 创建

  • Application.onCreate 里的网络请求(!)

  • BroadcastReceiver 长任务

Perfetto 与网络分析结合

新版 Perfetto 能录制网络包:

# data sources 里加
data_sources: {
    config {
        name: "android.network_packets"
    }
}

或者用 Network Inspector(Android Studio 自带),能直接看每个请求的时间、响应、stack。

自己用 Perfetto 分析冷启动

# 1. 把 App 杀掉
adb shell am force-stop com.example

# 2. 后台启动 trace
adb shell perfetto --async_start -c /sdcard/config.txt

# 3. 启动 App
adb shell am start -n com.example/.MainActivity

# 4. 等 5 秒,停止
sleep 5
adb shell kill -INT $(pidof perfetto)

# 5. 拉取 trace
adb pull /data/misc/perfetto-traces/trace.perfetto-trace

# 6. 上传到 ui.perfetto.dev

可以对比优化前后的两版 trace,看启动时间是否降了。

自动化测试

CI 里跑 Systrace 做性能回归:

@Test
fun verifyStartUpTime() {
    val startTime = System.currentTimeMillis()
    activityScenario.launch(MainActivity::class.java)
    // 验证主 Activity 完整显示
    onView(withId(R.id.main_content)).check(matches(isDisplayed()))
    val totalTime = System.currentTimeMillis() - startTime
    assertThat(totalTime).isLessThan(2000) // 启动小于 2 秒
}

但更精确的是:

// macrobenchmark
@RunWith(AndroidJUnit4::class)
class StartupBenchmarks {
    @get:Rule
    val rule = MacrobenchmarkRule()

    @Test
    fun coldStartup() = rule.measureRepeated(
        packageName = "com.example",
        metrics = listOf(StartupTimingMetric()),
        compilationMode = CompilationMode.DEFAULT,
        startupMode = StartupMode.COLD,
        iterations = 5
    ) {
        pressHome()
        startActivityAndWait()
    }
}

实战经验

1. 不要在生产环境开 trace

ATRACE_BEGIN 是有开销的。线上只在上报问题时偶尔抓。

2. 性能回归用 Baseline Profiles

只要加了 Baseline Profiles,冷启动跑 Systrace 会快 30%+。

3. 看 trace 别只看主线程

RenderThread、SurfaceFlinger、Binder 线程都可能出瓶颈。

4. 数据量太大时的过滤

Perfetto 录制 1 小时可能上 GB 体积。在 UI 里只关注一个进程的:

slice_filter: { 
    name_filter: "com.example.app*" 
}

5. UI 上善用快捷键

  • W: 放大时间窗口

  • A: 缩小时间窗口

  • D: 下一个 vsync(帧)

小结

Systrace 是 Android 性能分析的"老一辈",Perfetto 是"新贵"。两者协同覆盖大多数场景:日常快速排查用 Systrace,深入分析(小时级 trace、多源数据)用 Perfetto。理解 trace 数据格式,自定义事件插桩是进阶必修课。每个 Android 工程师都该掌握基本 trace 分析,定位性能问题远不止看 profiler。

下一篇进入前台服务与后台限制,理解 Android 14/15 在后台治理上的所有新规则。


评论