延迟分析工具: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都有了,怎么找到瓶颈?我总结了一个四步法,你试试看:

  1. 抓取完整Trace:用Perfetto录制一次完整的拍照流程。时长控制在5-10秒,别太长。
  2. 看整体时间线:先别钻细节。看整个流程分几个阶段,每个阶段耗时多少。比如:预览启动、对焦、Capture、处理、出图。
  3. 找「长条」:在时间线上,哪个阶段占的「条」最长?那就是嫌疑最大的瓶颈。我遇到过最夸张的一次,一个算法处理占了整个流程的70%。
  4. 钻进去看细节:双击那个长条,看里面有没有等待、锁竞争、Binder调用等。比如waitForNextBuffer如果很长,说明Buffer供应不足。

避坑指南:我曾经在分析一个预览卡顿问题时,盯着CPU频率看了半天,结果发现是GPU渲染线程被阻塞了。所以,不要只看CPU,也要看GPU、DDR、Binder等资源

5. 知识体系:一张图看懂延迟分析

下面这张图,是我自己整理的延迟分析知识体系。你把它当作地图,遇到问题按图索骥就行。

延迟分析知识体系 分析工具 Trace Tag 自定义Trace Systrace Perfetto SQL分析 CameraService Tag HAL层 Tag App层 Tag Java Trace.beginSection Native ATRACE_NAME 命名规范 延迟瓶颈定位四步法 CPU/GPU瓶颈 Buffer等待 Binder调用 锁竞争/死锁

6. 实战案例:一次预览卡顿的排查

最后分享一个真实案例。有一次,我负责的相机App在预览时偶尔会掉帧。用Perfetto抓Trace后,发现Camera3Stream::waitForNextBuffer这个Tag经常出现一个「长尾巴」,持续了30多毫秒。

顺着这个线索往下查,发现是HAL层在某个场景下Buffer分配慢了。进一步定位,是内存碎片导致的大块连续内存申请失败,触发了内存压缩。嗯,说白了就是内存管理的问题。

解决方案也很直接:在预览启动时预分配Buffer池,避免运行时动态申请。改完后,掉帧问题彻底解决。

总结一下:延迟分析不是玄学。用好Systrace/Perfetto,吃透Camera Trace Tag,该加自定义Trace就加,然后按四步法一步步排查。你也能成为性能优化高手。

公众号:蓝海资料掘金营,微信deep3321