# Perfetto使用技巧

## 一、Perfetto简介

### 1. 什么是Perfetto

Perfetto是Google开发的下一代系统级性能分析工具，从Android 9（API 28）开始集成到系统中。它是Systrace的升级版，提供了更强大的功能和更好的性能。

### 2. Perfetto的优势

- **更长的追踪时间**：支持数小时的长时间追踪
- **更丰富的数据源**：支持CPU、内存、网络、电源等多种数据源
- **更强大的分析能力**：支持SQL查询、自定义分析
- **更好的可视化**：Web UI界面更友好，交互更流畅
- **更灵活的配置**：支持配置文件，可以精确控制追踪内容

### 3. 适用场景

- 应用启动性能分析
- 游戏帧率问题分析
- 系统卡顿问题定位
- 内存泄漏排查
- CPU性能分析
- 网络性能分析
- 电源管理分析

## 二、环境准备与安装

### 1. 系统要求

- **Android版本**：Android 9（API 28）及以上
- **设备要求**：需要root权限或userdebug版本
- **开发环境**：ADB工具、Python 3.6+（可选）

### 2. 检查设备支持

```bash
# 检查Perfetto是否可用
adb shell perfetto --help

# 检查设备Android版本
adb shell getprop ro.build.version.release

# 检查设备是否支持Perfetto
adb shell getprop ro.build.version.sdk
```

### 3. 获取Perfetto工具

#### 3.1 通过Android Studio

Android Studio内置了Perfetto支持，可以直接使用Profiler功能。

#### 3.2 通过命令行

Perfetto已经集成在Android系统中，可以直接通过adb使用。

#### 3.3 通过Web UI

访问 https://ui.perfetto.dev/ 可以在线分析Trace文件。

### 4. 安装Python依赖（可选）

如果需要使用Python脚本处理Trace文件：

```bash
# 安装protobuf
pip install protobuf

# 安装perfetto Python库
pip install perfetto
```

## 三、基础使用

### 1. 快速开始

#### 1.1 最简单的录制

```bash
# 录制10秒的Trace
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace -t 10s

# 拉取Trace文件
adb pull /data/misc/perfetto-traces/trace trace.pb

# 在Web UI中打开
# 访问 https://ui.perfetto.dev/ 并上传trace.pb
```

#### 1.2 指定应用录制

```bash
# 录制指定应用的Trace
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace \
    -a com.example.app -t 10s
```

### 2. 命令行参数

#### 2.1 常用参数

```bash
# -c: 配置文件（- 表示使用默认配置）
adb shell perfetto -c -

# --out: 输出文件路径
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace

# -t: 录制时长
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace -t 10s
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace -t 5m
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace -t 1h

# -a: 指定应用包名
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace -a com.example.app

# --txt: 使用文本格式配置文件
adb shell perfetto -c /data/local/tmp/config.txt --out /data/local/tmp/trace.pb
```

#### 2.2 高级参数

```bash
# --background: 后台运行
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace --background

# --detach: 分离模式（录制完成后自动停止）
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace --detach

# --stop: 停止正在运行的录制
adb shell perfetto --stop
```

### 3. 配置文件使用

#### 3.1 配置文件格式

Perfetto支持两种配置文件格式：
- **文本格式（.txt）**：人类可读，易于编辑
- **二进制格式（.pb）**：更紧凑，性能更好

#### 3.2 基础配置文件

**基础配置（basic_config.txt）：**
```protobuf
buffers: {
    size_kb: 63488
    fill_policy: DISCARD
}

data_sources: {
    config {
        name: "linux.ftrace"
        ftrace_config {
            ftrace_events: "sched/sched_switch"
            ftrace_events: "sched/sched_waking"
            atrace_categories: "gfx"
            atrace_categories: "view"
            buffer_size_kb: 2048
        }
    }
}

duration_ms: 10000
```

#### 3.3 使用配置文件

```bash
# 1. 创建配置文件
cat > config.txt << 'EOF'
buffers: {
    size_kb: 63488
}
data_sources: {
    config {
        name: "linux.ftrace"
        ftrace_config {
            atrace_categories: "gfx"
            atrace_categories: "view"
        }
    }
}
duration_ms: 10000
EOF

# 2. 推送到设备
adb push config.txt /data/local/tmp/

# 3. 使用配置文件录制
adb shell perfetto -c /data/local/tmp/config.txt --out /data/local/tmp/trace.pb

# 4. 拉取Trace文件
adb pull /data/local/tmp/trace.pb trace.pb
```

## 四、常用配置模板

### 1. 启动性能分析配置

**startup_config.txt：**
```protobuf
buffers: {
    size_kb: 63488
    fill_policy: DISCARD
}

data_sources: {
    config {
        name: "linux.ftrace"
        ftrace_config {
            # CPU调度事件
            ftrace_events: "sched/sched_switch"
            ftrace_events: "sched/sched_waking"
            ftrace_events: "sched/sched_process_exit"
            ftrace_events: "sched/sched_process_free"
            ftrace_events: "task/task_newtask"
            ftrace_events: "task/task_rename"
            
            # 电源管理事件
            ftrace_events: "power/cpu_frequency"
            ftrace_events: "power/cpu_idle"
            ftrace_events: "power/suspend_resume"
            
            # ATrace类别
            atrace_categories: "am"           # Activity Manager
            atrace_categories: "wm"          # Window Manager
            atrace_categories: "gfx"          # Graphics
            atrace_categories: "view"         # View System
            atrace_categories: "binder_driver" # Binder Driver
            atrace_categories: "binder_lock"   # Binder Lock
            atrace_categories: "input"         # Input
            atrace_categories: "res"           # Resources
            atrace_categories: "dalvik"        # Dalvik VM
            
            buffer_size_kb: 4096
            drain_period_ms: 250
        }
    }
}

data_sources: {
    config {
        name: "android.surfaceflinger.frame"
    }
}

duration_ms: 10000
```

### 2. 游戏帧率分析配置

**jank_config.txt：**
```protobuf
buffers: {
    size_kb: 63488
    fill_policy: DISCARD
}

data_sources: {
    config {
        name: "linux.ftrace"
        ftrace_config {
            # CPU调度
            ftrace_events: "sched/sched_switch"
            ftrace_events: "sched/sched_waking"
            
            # 电源管理
            ftrace_events: "power/cpu_frequency"
            ftrace_events: "power/cpu_idle"
            
            # GPU事件（根据GPU型号选择）
            ftrace_events: "gfx/mali_gpu_total"
            ftrace_events: "gpu_mem_total/gpu_mem_total"
            
            # ATrace类别
            atrace_categories: "gfx"
            atrace_categories: "view"
            atrace_categories: "sched"
            atrace_categories: "freq"
            atrace_categories: "idle"
            
            buffer_size_kb: 8192
            drain_period_ms: 250
        }
    }
}

data_sources: {
    config {
        name: "android.surfaceflinger.frame"
    }
}

duration_ms: 30000
```

### 3. 内存分析配置

**memory_config.txt：**
```protobuf
buffers: {
    size_kb: 63488
    fill_policy: DISCARD
}

data_sources: {
    config {
        name: "linux.ftrace"
        ftrace_config {
            ftrace_events: "kmem/kmalloc"
            ftrace_events: "kmem/kfree"
            ftrace_events: "kmem/kmem_cache_alloc"
            ftrace_events: "kmem/kmem_cache_free"
            atrace_categories: "dalvik"
            atrace_categories: "gfx"
            buffer_size_kb: 4096
        }
    }
}

data_sources: {
    config {
        name: "android.java_hprof"
        target_buffer: 0
    }
}

duration_ms: 60000
```

### 4. 网络分析配置

**network_config.txt：**
```protobuf
buffers: {
    size_kb: 63488
    fill_policy: DISCARD
}

data_sources: {
    config {
        name: "linux.ftrace"
        ftrace_config {
            ftrace_events: "net/net_dev_xmit"
            ftrace_events: "net/net_dev_recv"
            atrace_categories: "network"
            buffer_size_kb: 2048
        }
    }
}

data_sources: {
    config {
        name: "linux.network_packets"
    }
}

duration_ms: 30000
```

### 5. 全系统分析配置

**full_system_config.txt：**
```protobuf
buffers: {
    size_kb: 63488
    fill_policy: DISCARD
}

data_sources: {
    config {
        name: "linux.ftrace"
        ftrace_config {
            # 所有常用事件
            ftrace_events: "sched/sched_switch"
            ftrace_events: "sched/sched_waking"
            ftrace_events: "power/cpu_frequency"
            ftrace_events: "power/cpu_idle"
            ftrace_events: "power/suspend_resume"
            
            # 所有ATrace类别
            atrace_categories: "am"
            atrace_categories: "wm"
            atrace_categories: "gfx"
            atrace_categories: "view"
            atrace_categories: "input"
            atrace_categories: "res"
            atrace_categories: "dalvik"
            atrace_categories: "binder_driver"
            atrace_categories: "binder_lock"
            atrace_categories: "sched"
            atrace_categories: "freq"
            atrace_categories: "idle"
            atrace_categories: "disk"
            atrace_categories: "load"
            atrace_categories: "sync"
            atrace_categories: "workq"
            atrace_categories: "memreclaim"
            atrace_categories: "regulators"
            atrace_categories: "binder_driver"
            atrace_categories: "binder_lock"
            
            buffer_size_kb: 8192
            drain_period_ms: 250
        }
    }
}

data_sources: {
    config {
        name: "android.surfaceflinger.frame"
    }
}

duration_ms: 60000
```

## 五、ATrace类别详解

### 1. 常用类别

| 类别 | 说明 | 使用场景 |
|------|------|----------|
| `gfx` | 图形渲染 | 帧率分析、渲染性能 |
| `view` | 视图系统 | UI性能、布局分析 |
| `am` | Activity Manager | 应用启动、Activity生命周期 |
| `wm` | Window Manager | 窗口管理、多窗口 |
| `input` | 输入事件 | 触摸响应、输入延迟 |
| `sched` | CPU调度 | CPU性能、任务调度 |
| `freq` | CPU频率 | 频率管理、性能调频 |
| `idle` | CPU空闲 | 电源管理、CPU使用率 |
| `binder_driver` | Binder驱动 | 跨进程通信 |
| `binder_lock` | Binder锁 | 锁竞争分析 |
| `res` | 资源管理 | 资源加载、资源管理 |
| `dalvik` | Dalvik VM | Java代码执行、GC |
| `disk` | 磁盘I/O | 文件读写、数据库操作 |
| `load` | 系统负载 | 系统负载分析 |
| `sync` | 同步操作 | 同步原语、锁 |
| `workq` | 工作队列 | 后台任务 |
| `memreclaim` | 内存回收 | 内存管理、GC |
| `network` | 网络 | 网络性能分析 |

### 2. 类别组合建议

**启动分析：**
```
am wm gfx view binder_driver binder_lock input res dalvik
```

**帧率分析：**
```
gfx view sched freq idle
```

**内存分析：**
```
dalvik gfx memreclaim
```

**网络分析：**
```
network disk
```

**全系统分析：**
```
am wm gfx view input res dalvik binder_driver binder_lock sched freq idle disk load sync workq memreclaim
```

## 六、高级功能

### 1. 自定义Trace标记

#### 1.1 Java/Kotlin代码

```java
import android.os.Trace;

public class MyClass {
    public void doSomething() {
        // 开始标记
        Trace.beginSection("my_custom_section");
        
        try {
            // 执行代码
            performOperation();
        } finally {
            // 结束标记（必须在finally中调用）
            Trace.endSection();
        }
    }
    
    private void performOperation() {
        Trace.beginSection("perform_operation");
        // 操作代码
        Trace.endSection();
    }
}
```

#### 1.2 C++代码

```cpp
#include <utils/Trace.h>

void doSomething() {
    // 开始标记
    ATRACE_BEGIN("my_custom_section");
    
    // 执行代码
    performOperation();
    
    // 结束标记
    ATRACE_END();
}

void performOperation() {
    ATRACE_BEGIN("perform_operation");
    // 操作代码
    ATRACE_END();
}
```

#### 1.3 异步操作标记

```java
import android.os.Trace;

public class AsyncTask {
    public void asyncOperation() {
        Trace.beginAsyncSection("async_operation", 0);
        
        // 启动异步操作
        new Thread(() -> {
            try {
                // 异步操作代码
                performAsyncWork();
            } finally {
                // 结束异步标记
                Trace.endAsyncSection("async_operation", 0);
            }
        }).start();
    }
}
```

### 2. 长时间追踪

#### 2.1 录制长时间Trace

```bash
# 录制5分钟
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace -t 5m

# 录制1小时
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace -t 1h

# 使用配置文件指定时长
# 在配置文件中设置 duration_ms: 3600000  # 1小时
```

#### 2.2 后台录制

```bash
# 后台录制
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace \
    --background -t 10m

# 检查录制状态
adb shell ps | grep perfetto

# 停止录制
adb shell perfetto --stop
```

### 3. 多进程追踪

#### 3.1 指定多个应用

```bash
# 追踪多个应用
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace \
    -a com.example.app1 -a com.example.app2 -t 10s
```

#### 3.2 追踪系统进程

```bash
# 追踪系统进程（需要root）
adb root
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace \
    -t 10s
```

### 4. 条件追踪

#### 4.1 基于触发器的追踪

```protobuf
# 在配置文件中添加触发器
data_sources: {
    config {
        name: "linux.ftrace"
        ftrace_config {
            atrace_categories: "gfx"
            # 触发器：当特定事件发生时开始追踪
            trigger_config {
                trigger_mode: START_TRACING
                trigger_name: "my_trigger"
            }
        }
    }
}
```

## 七、Trace文件分析

### 1. Web UI使用技巧

#### 1.1 基本操作

- **缩放**：鼠标滚轮或Ctrl+滚轮
- **平移**：鼠标拖拽或方向键
- **选择**：鼠标点击选择事件
- **搜索**：Ctrl+F 或点击搜索框
- **书签**：按M键标记当前位置
- **时间选择**：Shift+鼠标拖拽选择时间范围

#### 1.2 视图操作

- **展开/折叠**：点击进程/线程名称
- **高亮**：双击事件高亮显示
- **筛选**：使用筛选器过滤事件
- **排序**：点击列标题排序

#### 1.3 快捷键

- `W` / `S`：放大/缩小
- `A` / `D`：左移/右移
- `M`：添加书签
- `G`：跳转到书签
- `F`：查找
- `?`：显示所有快捷键

### 2. SQL查询

#### 2.1 基础查询

**查询所有帧信息：**
```sql
SELECT * FROM slice WHERE name = 'Choreographer#doFrame';
```

**查询掉帧：**
```sql
SELECT 
    ts,
    dur / 1000000.0 AS duration_ms
FROM slice 
WHERE name = 'Choreographer#doFrame' 
AND dur > 16666667
ORDER BY ts;
```

**查询CPU使用率：**
```sql
SELECT 
    cpu,
    COUNT(*) * 100.0 / (SELECT COUNT(*) FROM sched WHERE cpu = s.cpu) AS usage_percent
FROM sched s
GROUP BY cpu;
```

#### 2.2 高级查询

**查询启动时间：**
```sql
SELECT 
    (SELECT ts FROM slice WHERE name LIKE '%Choreographer#doFrame%' LIMIT 1) - 
    (SELECT ts FROM slice WHERE name LIKE '%startProcess%' LIMIT 1) 
    AS startup_time_ns;
```

**查询主线程阻塞时间：**
```sql
SELECT 
    SUM(dur) / 1000000.0 AS total_sleep_ms
FROM sched 
WHERE utid = (SELECT utid FROM thread WHERE name LIKE '%main%' LIMIT 1)
AND state = 'S';
```

**查询GC频率：**
```sql
SELECT 
    COUNT(*) AS gc_count,
    (MAX(ts) - MIN(ts)) / 1000000000.0 AS duration_sec,
    COUNT(*) * 1.0 / ((MAX(ts) - MIN(ts)) / 1000000000.0) AS gc_per_sec
FROM slice 
WHERE name LIKE '%GC%';
```

### 3. 性能指标分析

#### 3.1 帧率分析

**查看帧率：**
```
1. 在顶部选择 "Frame Timeline"
2. 查看每一帧的状态
3. 统计正常帧、掉帧数量
4. 计算平均帧率
```

**使用SQL计算帧率：**
```sql
SELECT 
    COUNT(*) * 1000000000.0 / (MAX(ts) - MIN(ts)) AS fps
FROM slice 
WHERE name = 'Choreographer#doFrame';
```

#### 3.2 CPU性能分析

**查看CPU频率：**
```
1. 在顶部选择 "CPU frequency"
2. 查看各核心频率变化
3. 检查是否有降频
```

**查看CPU使用率：**
```
1. 在顶部选择 "CPU usage"
2. 查看各核心使用情况
3. 检查是否有瓶颈
```

#### 3.3 内存分析

**查看内存使用：**
```
1. 在顶部选择 "Memory"
2. 查看内存使用趋势
3. 检查是否有内存泄漏
```

**查看GC活动：**
```
1. 在主线程中查找 "HeapTaskDaemon"
2. 查看GC频率和耗时
3. 分析GC对性能的影响
```

## 八、最佳实践

### 1. 录制Trace

1. **明确目标**：在录制前明确要分析的问题
2. **合适时长**：选择适当的追踪时间
   - 启动分析：5-10秒
   - 帧率分析：30-60秒
   - 内存分析：1-5分钟
   - 长时间监控：根据需要
3. **关键类别**：只追踪相关的类别，减少文件大小
4. **多次录制**：多次录制确保结果一致
5. **环境一致**：保持测试环境一致
   - 温度
   - 电量
   - 后台应用
   - 网络状态

### 2. 分析Trace

1. **系统化分析**：按照固定流程分析
2. **关键指标**：关注关键性能指标
3. **对比分析**：与基准版本或竞品对比
4. **深入分析**：找到根本原因
5. **验证优化**：优化后再次录制验证

### 3. 性能优化

1. **量化指标**：使用具体数值衡量优化效果
2. **多维度验证**：从多个角度验证优化效果
3. **回归测试**：确保优化没有引入新问题
4. **持续监控**：建立性能监控体系

## 九、常见问题与解决方案

### 1. 录制问题

**问题1：权限不足**
```
错误：perfetto: permission denied
解决：需要root权限或userdebug版本
```

**问题2：设备不支持**
```
错误：perfetto: command not found
解决：检查Android版本（需要Android 9+）
```

**问题3：配置文件格式错误**
```
错误：Failed to parse config
解决：检查配置文件格式，使用文本格式更易调试
```

### 2. 分析问题

**问题1：Trace文件过大**
```
解决：
1. 减少追踪时间
2. 减少追踪类别
3. 使用更小的缓冲区
4. 分段录制和分析
```

**问题2：找不到关键事件**
```
解决：
1. 确认追踪类别包含相关事件
2. 检查应用是否添加了Trace标记
3. 使用搜索功能查找
4. 查看相关进程和线程
```

**问题3：性能数据不准确**
```
解决：
1. 确认追踪配置正确
2. 检查是否有其他进程干扰
3. 多次录制取平均值
4. 对比其他性能工具
```

### 3. 性能问题

**问题1：录制影响性能**
```
解决：
1. 减少追踪类别
2. 使用较小的缓冲区
3. 减少追踪时间
4. 在性能测试时关闭不必要的追踪
```

**问题2：Web UI加载慢**
```
解决：
1. 减少Trace文件大小
2. 使用本地Perfetto工具
3. 分段分析Trace文件
```

## 十、实用脚本

### 1. 快速录制脚本

**quick_trace.sh：**
```bash
#!/bin/bash

# 快速录制Trace脚本
DURATION=${1:-10}
OUTPUT=${2:-trace.pb}

echo "开始录制 ${DURATION} 秒的Trace..."
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace -t ${DURATION}s

echo "拉取Trace文件..."
adb pull /data/misc/perfetto-traces/trace ${OUTPUT}

echo "Trace文件已保存为: ${OUTPUT}"
echo "可以在 https://ui.perfetto.dev/ 打开分析"
```

**使用方法：**
```bash
chmod +x quick_trace.sh
./quick_trace.sh 10 trace.pb
```

### 2. 应用启动分析脚本

**startup_trace.sh：**
```bash
#!/bin/bash

PACKAGE=${1:-com.example.app}
OUTPUT=${2:-startup_trace.pb}

echo "开始录制 ${PACKAGE} 的启动Trace..."
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace \
    -a ${PACKAGE} -t 10s

echo "拉取Trace文件..."
adb pull /data/misc/perfetto-traces/trace ${OUTPUT}

echo "启动Trace已保存为: ${OUTPUT}"
```

**使用方法：**
```bash
chmod +x startup_trace.sh
./startup_trace.sh com.example.app startup.pb
```

### 3. 批量分析脚本

**batch_analysis.sh：**
```bash
#!/bin/bash

# 批量录制和分析Trace
for i in {1..5}; do
    echo "录制第 ${i} 次Trace..."
    adb shell perfetto -c - --out /data/misc/perfetto-traces/trace_${i} -t 10s
    adb pull /data/misc/perfetto-traces/trace_${i} trace_${i}.pb
    echo "第 ${i} 次Trace已保存"
done

echo "所有Trace录制完成"
```

## 十一、进阶技巧

### 1. 性能基准建立

**建立性能基准：**
```
1. 在稳定版本上录制Trace
2. 记录关键性能指标
3. 建立性能基准数据库
4. 定期更新基准
```

### 2. 自动化性能测试

**集成到CI/CD：**
```
1. 在自动化测试中录制Trace
2. 自动分析关键指标
3. 设置性能阈值
4. 性能回归自动告警
```

### 3. 性能报告生成

**生成性能报告：**
```
1. 使用SQL查询提取数据
2. 使用脚本处理数据
3. 生成可视化报告
4. 定期发送性能报告
```

## 十二、参考资料

### 1. 官方文档

- Perfetto官方文档：https://perfetto.dev/
- Perfetto Web UI：https://ui.perfetto.dev/
- Android性能优化指南：https://developer.android.com/topic/performance

### 2. 相关工具

- Systrace：Android系统追踪工具
- Android Studio Profiler：IDE集成性能分析工具
- Traceview：Java代码性能分析工具

### 3. 学习资源

- Perfetto GitHub：https://github.com/google/perfetto
- Android性能优化最佳实践
- 系统性能分析案例

---

*最后更新：2024年*
