【性能工具】atrace、systrace、perfetto抓取的trace文件有何不同?

日常分析性能问题时,想要抓取trace文件,无非atrace、systrace、perfetto这三种方式,那么他们对于分析来说有什么区别呢?本文对此进行梳理。

一、三者本质关系

复制代码
┌─────────────────────────────────────────────────────┐
│                   数据来源层                          │
│  ftrace (Linux kernel) + Android atrace events       │
└──────────────┬──────────────────────────────────────┘
               │
    ┌──────────┼──────────┐
    ▼          ▼          ▼
  atrace     systrace   perfetto
 (采集工具)  (采集+展示) (采集+展示)

它们共享同一底层数据源,区别在于采集方式、格式和分析能力。

二、详细对比

2.1 atrace
复制代码
定位:纯命令行数据采集工具(Android底层)
输出:原始 ftrace 文本格式

工作原理:

复制代码
# atrace 本质是写入 /sys/kernel/debug/tracing/
atrace --list_categories        # 查看可用分类
atrace -t 10 -b 32768 gfx view wm am -o trace.atrace
输出格式示例(原始文本):
# tracer: nop
#
# entries-in-buffer/entries-written: 84780/84780   #P:8
#
#                              _-----=> irqs-off
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
        RenderThread-1234  [003] ...1  1234.567890: tracing_mark_write: B|1234|DrawFrame
        RenderThread-1234  [003] ...1  1234.578901: tracing_mark_write: E|1234|

适合场景:

脚本自动化采集

需要原始数据做二次处理

嵌入到 CI/CD 流程

2.2 systrace

plain

定位:Python脚本,采集atrace数据并转换为HTML可视化

输出:HTML文件(内嵌 Trace Viewer,基于 Chromium)

生命周期:Android 10+ 已标记为 deprecated

工作原理:

复制代码
systrace.py → 调用 atrace → 收集 ftrace 数据
           → 转换为 JSON → 生成 HTML(Catapult Trace Viewer)
使用方式:

# 旧方式
python systrace.py -t 10 -b 32768 gfx view wm am -o trace.html
# 或通过 Android Studio
# CPU Profiler → System Trace
输出特点:
trace.html
├── 内嵌 trace-viewer.js(Chromium项目)
├── 数据格式:JSON(Chrome Trace Format)
└── 直接用浏览器打开查看
时间线视图结构:
┌─────────────────────────────────────────┐
│  Process: com.example.app (pid 1234)    │
│  ├── Thread: main                       │
│  │   ├── [Choreographer#doFrame      ]  │
│  │   │   ├── [traversal             ]  │
│  │   │   └── [draw                  ]  │
│  ├── Thread: RenderThread              │
│  └── ...                               │
│  Kernel Threads                        │
│  ├── CPU 0 Frequency                   │
│  └── ...                               │
└─────────────────────────────────────────┘

适合场景:

分析帧率/卡顿(帧边界清晰可见)

UI 渲染流水线分析

快速分享(单个 HTML 文件)

旧项目维护(不建议新项目使用)

2.3 Perfetto
复制代码
定位:新一代全平台追踪框架
输出:.perfetto-trace(protobuf二进制)
官方推荐:Android 9+ 使用,Android 10+ 完整支持
架构:
┌─────────────────────────────────────────────────┐
│              Perfetto 架构                       │
│                                                  │
│  数据源(Data Sources)                            │
│  ├── ftrace (kernel events)                     │
│  ├── /proc/stat, /proc/meminfo                  │
│  ├── Heapprofd (heap profiling)                 │
│  ├── Android GPU counter                        │
│  ├── Chrome browser events                      │
│  └── 自定义 SDK (Java/C++/Rust)                 │
│              ↓                                   │
│  traced (后台服务,ring buffer管理)               │
│              ↓                                   │
│  输出:.perfetto-trace (protobuf)                │
└─────────────────────────────────────────────────┘

采集方式:

方式1:命令行
复制代码
adb shell perfetto \
  -c - --txt \
  -o /data/misc/perfetto-traces/trace \
<<EOF
buffers: {
    size_kb: 63488
    fill_policy: RING_BUFFER
}
data_sources: {
    config {
        name: "linux.ftrace"
        ftrace_config {
            ftrace_events: "sched/sched_switch"
            atrace_categories: "gfx"
            atrace_categories: "view"
            atrace_categories: "am"
        }
    }
}
data_sources: {
    config {
        name: "android.heapprofd"  # 额外能力:堆内存
        heapprofd_config {
            sampling_interval_bytes: 4096
            process_cmdline: "com.example.app"
        }
    }
}
duration_ms: 10000
EOF
方式2:使用 record_android_trace 脚本(推荐)
复制代码
curl -O https://raw.githubusercontent.com/google/perfetto/master/tools/record_android_trace
python3 record_android_trace -o trace.perfetto-trace -t 10s -b 64mb \
    gfx view am wm

代码插桩(SDK):

复制代码
kotlin
// Kotlin/Java
import android.os.Trace

// 简单方式(atrace兼容)
Trace.beginSection("MyOperation")
doSomething()
Trace.endSection()

// Perfetto SDK(更强大)
// build.gradle
implementation 'dev.perfetto:sdk:0.0.1'
cpp
// C++ 使用 Perfetto SDK
#include <perfetto.h>
PERFETTO_DEFINE_CATEGORIES(
    perfetto::Category("myapp").SetDescription("My app events"));

TRACE_EVENT("myapp", "MyFunction");
// 支持携带参数
TRACE_EVENT("myapp", "ProcessRequest", 
    "request_id", request_id,
    "size", data.size());

适合场景:

内存分析(native heap profiling)

长时间采集(ring buffer,可采集分钟级)

跨进程/跨平台分析(Android + Chrome)

SQL 查询分析(内置 TraceProcessor + SQLite)

自动化分析(Python API)

新项目首选

三、具体功能差异举例

3.1 帧分析(Frame Timeline)
复制代码
atrace 转换后:
┌────────────────────────────────────────┐
│ RenderThread                           │
│ [DrawFrame][DrawFrame][DrawFrame]      │
│                                        │
│ 只能看到函数名和耗时,                  │
│ 无法判断是否掉帧、Jank 类型            │
└────────────────────────────────────────┘

Perfetto 原生(Android 12+):
┌────────────────────────────────────────┐
│ Expected Timeline  [16ms][16ms][16ms]  │
│ Actual Timeline    [14ms][32ms!][15ms] │
│                          ↑            │
│                     自动标红 Jank      │
│                     点击显示原因:     │
│                     "GPU completion   │
│                      deadline missed" │
└────────────────────────────────────────┘
3.2 Slice 携带的参数信息
复制代码
// atrace 方式(无法携带参数)
ATRACE_BEGIN("processRequest");
// ... 处理逻辑
ATRACE_END();

// Perfetto SDK 方式(可携带丰富参数)
TRACE_EVENT("myapp", "processRequest",
    "request_id", req.id,          // 整数参数
    "url", req.url,                // 字符串参数  
    "size_bytes", req.body.size(), // 大小
    "is_cached", cached);          // 布尔值
cpp 复制代码
atrace 转换后在 UI 点击 slice:
┌─────────────────┐
│ Name: processRequest │
│ Start: 1234.56ms     │
│ Duration: 23.4ms     │
│ (无其他信息)         │
└─────────────────┘

Perfetto 原生在 UI 点击 slice:
┌─────────────────────────┐
│ Name: processRequest    │
│ Start: 1234.56ms        │
│ Duration: 23.4ms        │
│ ─── Arguments ───       │
│ request_id: 42          │
│ url: /api/user/profile  │
│ size_bytes: 1024        │
│ is_cached: false        │
└─────────────────────────┘
3.3 CPU Wakeup 分析
复制代码
atrace 转换后:
线程 A 等待中... → 突然被唤醒
(无法知道谁唤醒了它)

Perfetto 原生:
线程 A 等待中... → [wakeup by 线程B] → 运行
                     ↑
              点击可跳转到线程B
              的对应位置,显示
              完整唤醒调用栈
3.4 SQL 查询能力对比
sql 复制代码
-- atrace 转换后可以查的(基础):
SELECT name, dur FROM slice 
WHERE dur > 16000000
ORDER BY dur DESC;

-- 有数据但有限:
-- slice 表:有
-- sched 表:部分有
-- counter 表:基础有

-- Perfetto 原生可以查的(丰富):
-- 查询导致Jank的帧
SELECT 
    f.ts, f.dur,
    f.jank_type,
    f.on_time_finish
FROM frame_slice f
WHERE f.jank_type != 'none';

-- 查询内存分配热点(需heapprofd数据)
SELECT 
    h.name as function,
    SUM(h.size) as total_bytes,
    COUNT(*) as alloc_count
FROM heap_profile_allocation h
GROUP BY h.name
ORDER BY total_bytes DESC
LIMIT 20;

-- 查询线程唤醒链
SELECT 
    t1.name as waiter,
    t2.name as waker,
    w.ts,
    w.dur as wait_time
FROM thread_state w
JOIN thread t1 ON w.utid = t1.utid
JOIN thread t2 ON w.waker_utid = t2.utid
WHERE w.state = 'S'  -- sleeping
  AND w.dur > 10000000;  -- 等待超过10ms

四、一个直观的信息量对比

复制代码
假设分析一个卡顿问题:

用 atrace 转换后分析:
─────────────────────
✅ 能看到:哪个函数耗时长(23ms > 16ms)
✅ 能看到:发生在哪个线程
✅ 能看到:同期 CPU 频率
❌ 不知道:为什么慢(内存分配?锁等待?)
❌ 不知道:是否有频繁的小内存分配
❌ 不知道:具体是哪行代码
❌ 不知道:GPU 侧是否也有延迟

用 Perfetto 原生分析:
─────────────────────
✅ 能看到:函数耗时 + 内部调用栈
✅ 能看到:这23ms里有18ms在等锁(sched状态)
✅ 能看到:持锁的是哪个线程在做什么
✅ 能看到:同期发生了 2MB 的 native 内存分配
✅ 能看到:具体分配来自哪个调用路径(火焰图)
✅ 能看到:GPU 完成时间比预期晚了 5ms
✅ 能看到:帧被系统标记为 AppDeadlineMissed Jank

五、总结

核心结论:三者数据来源相同,perfetto 是进化版,在数据丰富度、分析能力、工具链上全面超越前两者。新项目直接用 perfetto,老项目的 systrace trace 可通过 traceconv 转换复用。

相关推荐
张小潇2 小时前
AOSP15 WMS/AMS系统开发 - 窗口层级源码分析
android·前端
努力努力再努力wz4 小时前
【MySQL入门系列】掌握表数据的 CRUD:DML 核心语法与执行逻辑解析
android·开发语言·数据结构·数据库·c++·b树·mysql
zh_xuan6 小时前
Android gradle任务
android·gradle构建
Grackers7 小时前
Android Perfetto 系列 10:Binder 调度与锁竞争
android·binder
李白你好7 小时前
Android 自动化渗透测试指令生成
android·自动化
CeshirenTester8 小时前
Claude Code 不只是会写代码:这 10 个 Skills,才是效率分水岭
android·开发语言·kotlin
山峰哥9 小时前
SQL性能飞跃:从索引策略到查询优化的全链路实战指南
数据库·sql·性能优化·深度优先
朝星10 小时前
Android开发[2]:Flow
android·kotlin
zzb158010 小时前
Android Activity 与 Intent 学习笔记
android·笔记·学习