17、性能分析工具使用:Systrace/Perfetto使用技巧、Simpleperf CPU采样、Memory Profiler、GPU Inspector、Camera Trace点添加

做Camera性能优化,说白了就是跟时间赛跑。你想想看,从用户按下快门到出图,中间几百毫秒里到底发生了什么?哪个环节拖了后腿?没有趁手的工具,你只能靠猜。

我个人习惯,先把工具链搭好。工欲善其事,必先利其器。今天我就把压箱底的那几个工具用法,掰开了揉碎了讲给你听。

核心观点:性能优化不是靠感觉,而是靠数据。Systrace/Perfetto看整体流程,Simpleperf抓CPU热点,Memory Profiler查内存泄漏,GPU Inspector盯渲染瓶颈。四板斧下去,问题基本无处遁形。
Camera性能分析工具矩阵 性能瓶颈定位 Systrace/Perfetto 整体流程追踪 Simpleperf CPU采样热点 Memory Profiler 内存泄漏检测 GPU Inspector 渲染管线分析 Camera Trace点 + 自定义标记 = 精准定位

17.1 Systrace / Perfetto:看全局的利器

Systrace 和 Perfetto 其实是一脉相承的东西。Perfetto 是 Systrace 的下一代,功能更强,UI也更现代。我建议你直接上 Perfetto,除非你还在维护 Android 9 以下的旧平台。

用这两个工具,核心就一句话:找到那个「不该那么长」的区间

举个例子。我在项目中遇到过预览启动慢的问题。打开 Perfetto 一看,从 App 发起请求到 HAL 返回第一帧,中间有个 200ms 的空白。点进去发现,原来是底层在等一个 sensor 的初始化完成。这个等待完全可以在上层准备 UI 的时候并行做掉。

使用技巧:
  • 抓取时加上 -a 你的包名,只关注自己的进程,不然信息太多看花眼
  • 善用「A」键打标记,记录操作时间点,方便对照
  • 重点关注 BufferQueueHALCameraService 这几个线程

17.2 Simpleperf:CPU 采样的瑞士军刀

Simpleperf 是 Android 官方的 CPU 性能分析工具,比 perf 更友好。它做的是采样——每隔一段时间看看 CPU 正在执行哪个函数,最后统计出热点。

我一般这么用:

# 先找到 camera provider 的 PID
adb shell ps | grep camera

# 采样 10 秒
adb shell simpleperf record -p <PID> -e cpu-clock -f 1000 --duration 10

# 生成报告
adb shell simpleperf report --full-callgraph

输出结果里,你会看到类似这样的东西:

Overhead Symbol Shared Object
15.2% HAL3ProcessRequest camera.hal.so
8.7% JpegEncode libjpeg.so
5.3% memcpy libc.so

看到 memcpy 占 5% 以上,你就要警觉了。我曾经在一个项目里发现 memcpy 占了 12%,最后追查下来是 YUV 转 JPEG 时反复拷贝了三次。改成零拷贝后,拍照速度直接快了 30%。

注意:Simpleperf 采样频率不要设太高。1000Hz 够用了。设到 4000Hz 以上,采样本身就会拖慢系统,数据反而不准。

17.3 Memory Profiler:别让内存成为隐形杀手

Camera 是吃内存大户。一张 12MP 的 raw 图就 20MB 左右,再加上中间 buffer、算法库的临时内存,稍不注意就 OOM 了。

Android Studio 自带的 Memory Profiler 够用。我习惯这么操作:

  • 先跑一遍完整的拍照流程,记录内存峰值
  • 然后反复进出预览界面,看 GC 次数和内存回收情况
  • 重点关注 Native Heap,因为 Camera HAL 层很多内存是 C++ 分配的

嗯,这里要注意。Java 层的内存泄漏相对好查,但 Native 层的泄漏就麻烦了。我建议配合 libmemunreachable 工具一起用,它能帮你找到 native 层谁没释放。

避坑指南:我曾经遇到一个 case,每次拍照后 native heap 涨 2MB 不回落。查了三天,最后发现是 HAL 层的一个 buffer pool 没有做回收。用 Memory Profiler 配合 dumpsys meminfo 才定位到。

17.4 GPU Inspector:渲染管线的 X 光机

GPU Inspector 是 Android 12 以后才正式推出的。它能看到 GPU 的每一帧渲染耗时、顶点数、片段着色器负载等。

对于 Camera 来说,GPU 主要干两件事:

  1. 预览画面的合成(SurfaceFlinger 那边)
  2. 滤镜、美颜等 GPU 算法的执行

打开 GPU Inspector,如果看到 Frame Duration 超过 16ms(60fps 的阈值),那就说明 GPU 扛不住了。这时候要么降低分辨率,要么优化 shader。

我记得有个项目,美颜算法在 GPU 上跑,一帧要 25ms。后来发现是循环里有个不必要的纹理采样,去掉后降到 8ms。这种问题,没有 GPU Inspector 根本看不出来。

17.5 Camera Trace 点:给你的代码装上「行车记录仪」

前面几个工具都是外挂式的。但有时候,你需要在自己代码里埋点,才能精准知道某个函数花了多久。

Android 提供了 Trace 类,用法很简单:

// Java/Kotlin 层
Trace.beginSection("HAL3:CaptureRequest");
// ... 你的代码 ...
Trace.endSection();

// Native 层
#include <utils/Trace.h>
ATRACE_CALL();  // 自动在函数进出时打点

加了这些 Trace 点之后,再跑 Systrace/Perfetto,你就能看到自己定义的标签了。我习惯在每个关键路径上都加:

  • App:onCreate → 应用启动
  • HAL:configureStreams → 配置流
  • HAL:processCaptureRequest → 拍照请求
  • Algo:JpegEncode → JPEG 编码
我的经验:Trace 点不要加太多,否则 trace 文件会变得巨大。我一般只在「跨模块调用」和「耗时超过 5ms 的函数」上加。加多了反而干扰分析。

最后说一句。工具终究是工具,关键还是你得知道「要查什么」。我见过有人拿着 Perfetto 看了半天,说「看不出问题」。其实不是工具不行,是他自己没想清楚——到底是想优化启动速度?还是拍照延迟?还是预览帧率?目标明确了,工具才能发挥威力。

总结一下我的工作流:
  1. 先用 Perfetto 看整体流程,找到异常区间
  2. 用 Simpleperf 定位 CPU 热点函数
  3. 用 Memory Profiler 检查内存泄漏
  4. 用 GPU Inspector 确认渲染瓶颈
  5. 最后加自定义 Trace 点,做精细化验证
这套组合拳打下来,90% 的性能问题都能揪出来。

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