Perfetto Trace 分析报告
Trace 文件 : trace_file.perfetto-trace
分析时间 : 2026-05-12 12:13
分析工具: trace_processor_shell
1. 执行摘要
| 指标 | 结果 | 评级 |
|---|---|---|
| 掉帧率 | 18.31% | 🔴 严重 |
| 锁竞争次数 | 11 次 | 🟡 中等 |
| 主线程长阻塞 | 816 次 (>5ms) | 🔴 严重 |
| 最大单帧耗时 | 87.8ms | 🔴 严重 |
2. 帧渲染分析
| 指标 | 数值 |
|---|---|
| 总帧数 | 590 |
| 掉帧数 | 108 |
| 掉帧率 | 18.31% |
| 平均帧耗时 | 9.88ms |
| 最大帧耗时 | 87.8ms |
60fps 标准下,帧耗时超过 16.67ms 即视为掉帧。当前掉帧率 18.31%,用户体验会有明显卡顿感。
3. 锁竞争分析
3.1 总体分布
| 指标 | 数值 |
|---|---|
| 锁竞争次数 | 11 次 |
| 总等待时间 | 6.67ms |
| 平均等待 | 0.61ms |
| 最大等待 | 6.34ms |
3.2 严重锁竞争详情(Top 5)
| 等待时间 | 持有者 | 阻塞位置 |
|---|---|---|
| 6.34ms | Binder:585_5 | PowerManagerService.acquireWakeLockInternal |
| 0.13ms | InputDispatcher | Message.recycleUnchecked |
| 0.10ms | Binder:585_5 | MessageQueue.enqueueMessage |
| 0.04ms | Binder:585_5 | MessageQueue.enqueueMessage |
| 0.03ms | RenderThread | MessageQueue.nativeWake |
3.3 主线程锁竞争
| 等待时间 | 持有者 | 阻塞位置 |
|---|---|---|
| 0.13ms | InputDispatcher | Message.recycleUnchecked |
| 0.03ms | RenderThread | MessageQueue.nativeWake |
| 0.01ms | RenderThread | MessageQueue.enqueueMessage |
| 0.005ms | Binder:585_5 | WindowManagerService.addWindow |
| 0.001ms | InputDispatcher | MessageQueue.enqueueMessage |
关键发现: 主线程多次被 RenderThread 和系统 Binder 线程阻塞,主要发生在 MessageQueue 操作上。
4. 主线程耗时分析(Top 10)
| 操作 | 次数 | 平均耗时 | 最大耗时 | 总耗时 |
|---|---|---|---|---|
| animator | 15 | 101.16ms | 134.78ms | 1517.41ms |
| traversal | 77 | 11.41ms | 69.99ms | 878.69ms |
| draw | 75 | 11.00ms | 69.95ms | 825.05ms |
| animator:scaleX | 1 | 350.60ms | 350.60ms | 350.60ms |
| animator:scaleY | 1 | 350.56ms | 350.56ms | 350.56ms |
| binder reply | 51 | 5.97ms | 21.12ms | 304.64ms |
| HIDL::IComposerClient::executeCommands | 49 | 6.08ms | 21.09ms | 298.07ms |
| rcCompose encode | 40 | 6.61ms | 20.49ms | 264.28ms |
关键发现:
animator:scaleX/Y单次耗时 350ms+,严重阻塞主线程animator操作平均 101ms,远超 16.67ms 帧预算
5. ANR 风险分析
| 指标 | 数值 |
|---|---|
| 长阻塞次数 (>5ms) | 816 次 |
| 最短阻塞 | 5.09ms |
| 平均阻塞 | 18.25ms |
| 最大阻塞 | 350.60ms |
风险等级 : 🔴 高
存在大量主线程阻塞事件,最大阻塞达 350ms,接近 ANR 阈值(5秒)。
6. CPU 调度分析(Runnable 等待 Top 5)
| 线程 | 等待次数 | 平均等待 | 最大等待 | 总等待 |
|---|---|---|---|---|
| AudioOut_D | 1313 | 0.12ms | 14.18ms | 153.28ms |
| HwBinder:347_3 | 1338 | 0.11ms | 11.25ms | 145.84ms |
| RenderThread | 875 | 0.14ms | 12.68ms | 122.72ms |
| surfaceflinger | 1381 | 0.08ms | 30.48ms | 113.32ms |
| kworker/1:2 | 117 | 0.91ms | 51.49ms | 106.07ms |
7. 根因总结
主要问题
-
动画性能问题 (最严重)
animator:scaleX/Y单次执行 350ms+- 属性动画在主线程执行耗时操作
-
掉帧严重
- 掉帧率 18.31%,远超健康标准 (<5%)
- 最大单帧 87.8ms,是标准 16.67ms 的 5 倍
-
主线程阻塞
- 816 次长阻塞事件
- 被 RenderThread 和 Binder 线程频繁阻塞
-
锁竞争
- MessageQueue 锁竞争频繁
- PowerManagerService 锁单次阻塞 6.34ms
8. 优化建议
立即执行
markdown
1. 动画优化
├── 使用 ObjectAnimator.setDuration() 控制时长
├── 复杂动画使用 RenderThread (硬件加速)
└── 避免在动画回调中执行耗时操作
2. 减少主线程阻塞
├── 将 scaleX/scaleY 动画移到子线程计算
├── 使用 Choreographer.postFrameCallback 替代频繁 post
└── 减少 Binder 同步调用,改用异步
中期优化
markdown
3. 布局优化
├── 减少 View 层级,降低 traversal 耗时
├── 使用 ConstraintLayout 替代嵌套布局
└── 避免在 onDraw 中创建对象
4. 锁优化
├── 减少跨线程 MessageQueue 操作
├── 使用 HandlerThread 隔离耗时消息
└── 避免在动画期间触发 WakeLock 申请
9. 关键 SQL 查询
sql
-- 查询掉帧详情
SELECT * FROM actual_frame_timeline_slice
WHERE dur > 16666666 ORDER BY dur DESC;
-- 查询主线程长阻塞
SELECT * FROM __intrinsic_slice s
JOIN thread t ON s.track_id = t.utid
WHERE t.is_main_thread = 1 AND s.dur > 50000000;
-- 查询锁竞争
SELECT * FROM __intrinsic_slice
WHERE name LIKE '%monitor contention%' ORDER BY dur DESC;
报告生成: Perfetto Trace Processor