延迟分析工具:Systrace/Perfetto使用、Camera Trace Tag、自定义Trace点、延迟瓶颈定位方法
做相机性能优化,说白了就是跟时间赛跑。你想想看,用户按下快门到出图,中间几百毫秒甚至几十毫秒的差距,体验就是天壤之别。我入行那会儿,最头疼的就是「卡顿」——明明代码逻辑没问题,但就是慢。后来才明白,没有工具,你就是在黑盒里瞎摸。
今天咱们聊的,就是打开这个黑盒的钥匙。延迟分析工具,我个人的经验是:用好Systrace和Perfetto,再配合Camera Trace Tag,基本能解决90%的性能瓶颈问题。
1. Systrace vs Perfetto:你该用哪个?
先说说这两个工具。Systrace是老牌工具了,Android 10之前是主力。Perfetto是它的升级版,现在Google主推。我建议你直接上Perfetto,除非你还在维护老项目。
| 特性 | Systrace | Perfetto |
|---|---|---|
| 数据源 | 有限(Ftrace + Atrace) | 丰富(Ftrace + Atrace + heapprofd + 自定义) |
| UI界面 | 老旧,基于Web | 现代,支持SQL分析 |
| 长Trace支持 | 差,容易丢帧 | 好,支持小时级录制 |
| 自定义Trace | 需要手动加代码 | 同样需要,但解析更灵活 |
我在项目中遇到过一个问题:用Systrace抓一个连续拍照的场景,结果Trace文件太大,浏览器直接崩了。换成Perfetto后,同样的数据量,流畅多了。所以,新项目直接用Perfetto,别犹豫。
2. Camera Trace Tag:系统帮你埋好的点
Android相机框架里,Google已经帮你埋了很多Trace点。这些点分布在HAL、CameraService、App层。你不需要自己加代码,直接抓Trace就能看到。
常用的Camera Trace Tag包括:
CameraService::connect:打开相机耗时CameraDeviceClient::setStreamConfigured:配置流耗时Camera3Device::processCaptureRequest:下发Capture请求Camera3Stream::waitForNextBuffer:等待Buffer返回ResultProcessor::processResult:处理结果回调
嗯,这里要注意:不同厂商的HAL层可能自定义了额外的Trace点。比如高通平台会有mct_pipeline_process之类的。我建议你先跑一次全Trace,看看有哪些Tag可用。
核心思路:不要重复造轮子。先用系统自带的Trace Tag定位到大概范围,再决定是否需要加自定义Trace点。
3. 自定义Trace点:精准定位你的代码
系统Trace Tag只能帮你看到框架层。你自己的App代码、算法库、中间件,需要手动加Trace点。说白了,就是给代码打上「时间戳标签」。
Android提供了两种方式:
3.1 Java/Kotlin层
import android.os.Trace;
// 开始Trace
Trace.beginSection("MyApp::captureProcessing");
// ... 你的耗时操作 ...
// 结束Trace
Trace.endSection();
3.2 Native层(C++)
#include <utils/Trace.h>
// 使用ScopedTrace,自动管理生命周期
{
ATRACE_NAME("HAL::processRequest");
// ... 你的代码 ...
}
我个人习惯在关键路径上加Trace点,比如:
- 从App下发请求到HAL的入口
- 算法处理前后(如降噪、HDR合成)
- Buffer从Surface到消费端的流转
小技巧:Trace点的命名建议用「模块::子模块::操作」的格式。比如App::Capture::onShutter,这样在Perfetto里一眼就能看出层级关系。
4. 延迟瓶颈定位方法:实战四步法
工具和Tag都有了,怎么找到瓶颈?我总结了一个四步法,你试试看:
- 抓取完整Trace:用Perfetto录制一次完整的拍照流程。时长控制在5-10秒,别太长。
- 看整体时间线:先别钻细节。看整个流程分几个阶段,每个阶段耗时多少。比如:预览启动、对焦、Capture、处理、出图。
- 找「长条」:在时间线上,哪个阶段占的「条」最长?那就是嫌疑最大的瓶颈。我遇到过最夸张的一次,一个算法处理占了整个流程的70%。
- 钻进去看细节:双击那个长条,看里面有没有等待、锁竞争、Binder调用等。比如
waitForNextBuffer如果很长,说明Buffer供应不足。
避坑指南:我曾经在分析一个预览卡顿问题时,盯着CPU频率看了半天,结果发现是GPU渲染线程被阻塞了。所以,不要只看CPU,也要看GPU、DDR、Binder等资源。
5. 知识体系:一张图看懂延迟分析
下面这张图,是我自己整理的延迟分析知识体系。你把它当作地图,遇到问题按图索骥就行。
6. 实战案例:一次预览卡顿的排查
最后分享一个真实案例。有一次,我负责的相机App在预览时偶尔会掉帧。用Perfetto抓Trace后,发现Camera3Stream::waitForNextBuffer这个Tag经常出现一个「长尾巴」,持续了30多毫秒。
顺着这个线索往下查,发现是HAL层在某个场景下Buffer分配慢了。进一步定位,是内存碎片导致的大块连续内存申请失败,触发了内存压缩。嗯,说白了就是内存管理的问题。
解决方案也很直接:在预览启动时预分配Buffer池,避免运行时动态申请。改完后,掉帧问题彻底解决。
总结一下:延迟分析不是玄学。用好Systrace/Perfetto,吃透Camera Trace Tag,该加自定义Trace就加,然后按四步法一步步排查。你也能成为性能优化高手。