21 KiB
21 KiB
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. 检查设备支持
# 检查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文件:
# 安装protobuf
pip install protobuf
# 安装perfetto Python库
pip install perfetto
三、基础使用
1. 快速开始
1.1 最简单的录制
# 录制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 指定应用录制
# 录制指定应用的Trace
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace \
-a com.example.app -t 10s
2. 命令行参数
2.1 常用参数
# -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 高级参数
# --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):
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 使用配置文件
# 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:
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:
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:
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:
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:
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代码
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++代码
#include <utils/Trace.h>
void doSomething() {
// 开始标记
ATRACE_BEGIN("my_custom_section");
// 执行代码
performOperation();
// 结束标记
ATRACE_END();
}
void performOperation() {
ATRACE_BEGIN("perform_operation");
// 操作代码
ATRACE_END();
}
1.3 异步操作标记
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
# 录制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 后台录制
# 后台录制
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 指定多个应用
# 追踪多个应用
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace \
-a com.example.app1 -a com.example.app2 -t 10s
3.2 追踪系统进程
# 追踪系统进程(需要root)
adb root
adb shell perfetto -c - --out /data/misc/perfetto-traces/trace \
-t 10s
4. 条件追踪
4.1 基于触发器的追踪
# 在配置文件中添加触发器
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 基础查询
查询所有帧信息:
SELECT * FROM slice WHERE name = 'Choreographer#doFrame';
查询掉帧:
SELECT
ts,
dur / 1000000.0 AS duration_ms
FROM slice
WHERE name = 'Choreographer#doFrame'
AND dur > 16666667
ORDER BY ts;
查询CPU使用率:
SELECT
cpu,
COUNT(*) * 100.0 / (SELECT COUNT(*) FROM sched WHERE cpu = s.cpu) AS usage_percent
FROM sched s
GROUP BY cpu;
2.2 高级查询
查询启动时间:
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;
查询主线程阻塞时间:
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频率:
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计算帧率:
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
- 明确目标:在录制前明确要分析的问题
- 合适时长:选择适当的追踪时间
- 启动分析:5-10秒
- 帧率分析:30-60秒
- 内存分析:1-5分钟
- 长时间监控:根据需要
- 关键类别:只追踪相关的类别,减少文件大小
- 多次录制:多次录制确保结果一致
- 环境一致:保持测试环境一致
- 温度
- 电量
- 后台应用
- 网络状态
2. 分析Trace
- 系统化分析:按照固定流程分析
- 关键指标:关注关键性能指标
- 对比分析:与基准版本或竞品对比
- 深入分析:找到根本原因
- 验证优化:优化后再次录制验证
3. 性能优化
- 量化指标:使用具体数值衡量优化效果
- 多维度验证:从多个角度验证优化效果
- 回归测试:确保优化没有引入新问题
- 持续监控:建立性能监控体系
九、常见问题与解决方案
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:
#!/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/ 打开分析"
使用方法:
chmod +x quick_trace.sh
./quick_trace.sh 10 trace.pb
2. 应用启动分析脚本
startup_trace.sh:
#!/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}"
使用方法:
chmod +x startup_trace.sh
./startup_trace.sh com.example.app startup.pb
3. 批量分析脚本
batch_analysis.sh:
#!/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年