在提交 Camera 性能问题给高通分析之前,先完成以下排查步骤:
让性能团队做 breakdown:
- CPU 频率是否跑在预期值?
- CPU 调度策略是否正确?(大核/小核分配)
- Power hint / perflock 是否生效?
- 如果是系统负载导致的掉帧 → 先通性能团队调参
# 日志输出会影响系统负载,关掉所有日志后再测试
adb shell stop logd
adb shell stop logcat
# 在 camxoverridesettings.txt 中关闭所有日志
logVerboseMask=0x00000
logInfoMask=0x00000
traceGroupsEnable=0x00000
logEntryExitMask=0x00000
systemLogEnable=FALSE
# kernel 日志也关掉
adb shell "echo 0x0 > /sys/module/cam_debug_util/parameters/debug_mdl"
在 systrace 中检查 SOF(Start of Frame)IRQ:
正常 30fps → SOF 间隔 33.3ms
正常 60fps → SOF 间隔 16.6ms
如果 SOF 间隔不稳定 → sensor 或 3A 问题
测试性能必须使用 perf build(非 debug build)
debug build 有额外的日志和检查操作,影响性能数据
从 App 调用 openCamera() 到第一帧预览显示:
T0: App 调用 openCamera()
T1: HAL open() 返回 ChiContext 初始化、EEPROM 读取 (~100ms)
T2: configure_streams() Pipeline 创建、Buffer 分配 (~80ms)
T3: 第一帧完成 (CSLMessageHandler) Sensor 曝光 + ISP 处理 (~50ms)
adb logcat -v threadtime -d | grep -E "onOpened|onConfigured|CSLMessageHandler"
① 尽早 open camera
App 端尽早调用 openCamera(),不等 UI 完全就绪
② 减少 open 中的延迟
open camera 只做 HAL open + 注册回调,不需要延迟
不要在这里做耗时的 I2C 通信
③ 延迟创建非实时 Session
Offline Session / OIS 初始化可以延迟创建
高通有 patch 支持 defer non-real time session
④ 优化 Sensor I2C setting array
减少不必要的寄存器设置(缩短 configure_streams 时间)
提高 I2C 总线速度(1MHz 代替 400KHz)
⑤ App 侧优化
不等 SurfaceView 就绪再创建 Session
先 createSession,第一帧 buffer ready 时间晚于 SurfaceView 就绪
从 logcat 抓到的各阶段耗时:
10:00:00.000 - openCamera()
10:00:00.250 - onOpened() ← 250ms
10:00:00.380 - onConfigured() ← 130ms
10:00:00.480 - CSLMessageHandler ← 100ms
logcat:
[CamX] [Sensor] EEPROM read completed: 45ms
[CamX] [CHI] ChiContext::Create() completed: 250ms
分析:
T0-T1 = 250ms → HAL open 太慢,EEPROM 占用 45ms
T1-T2 = 130ms → configure_streams 偏慢
T2-T3 = 100ms → 第一帧延迟正常
解决的优先级:
① 减少 EEPROM 读取时间(I2C 速度不够)
② 优化 I2C setting array(移除不必要的配置)
③ 延迟非实时 Session 的创建(Offline/OIS)
帧间隔 = max(曝光时间, ISP 处理时间)
帧率 = 1000ms / 帧间隔
30fps → 帧间隔 33ms
60fps → 帧间隔 16ms
# 方法 1: CamX FPS 日志
echo "enableFPSLog=1" >> camxoverridesettings.txt
# logcat: [FPS] Current FPS: 29.8
# 方法 2: CSLMessageHandler 时间戳
adb logcat | grep "CSLMessageHandler"
# 相邻 frameMessage.timestamp 的差 = 帧间隔
# 方法 3: SOF trace(高通推荐,最精确)
adb root
adb shell "echo 1 > /d/tracing/events/camera/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/options/record-tgid"
# 然后抓 systrace,在 trace 中搜 SOF
echo "dumpNodeProcessingInfo=1" >> camxoverridesettings.txt
echo "traceGroupsEnable=0x10080" >> camxoverridesettings.txt
echo "traceOutputEnable=0x10080" >> camxoverridesettings.txt
adb reboot
# logcat 输出:
# [NodeProcessing] IFE: 2.1ms BPS: 3.5ms IPE: 2.8ms
使用 systrace 查看 Node 处理时间:
在 systrace 中搜索 "Node::%s ProcessRequest":
CAMX_TRACE_SYNC_BEGIN(CamxLogGroupCore, "Node::%s ProcessRequest")
→ Node 开始处理
CAMX_TRACE_SYNC_END(CamxLogGroupCore)
→ Node 处理结束
HW Node 的 ProcessRequest trace 包括了提交到硬件和等待 CSL Fence 的时间
SW Node 的 ProcessRequest trace 就是 CPU 处理时间
在 systrace 中搜索 "HAL3:RequestTrace":
static int process_capture_request → camxhal3.cpp
CAMX_TRACE_ASYNC_BEGIN("HAL3:RequestTrace")
→ Request 进入 CamX 管线
Session::AdvanceMinExpectedResult → camxsession.cpp
CAMX_TRACE_ASYNC_END("HAL3:RequestTrace")
→ Request 处理完成,结果返回
这个 trace span 完整覆盖了从 request 进入 CamX 到 result 返回的时间。
可以精确测量每帧的延迟。
在 systrace 中看线程状态条的颜色:
灰色(Sleeping) → 线程在休眠,没有工作可做
蓝色(Runnable) → 线程可以被调度,但还没被选中
绿色(Running) → 线程正在 CPU 上运行
红色(Interruptible)→ 线程在内核中等待锁(可能 I/O 负载过高)
Camera 性能优化时重点关注:
- Node 处理线程是不是长时间在红色状态(I/O 瓶颈)
- CPU 核心是不是合理分配(大核跑高负载 Node)
① Node 处理时间过长
开启 dumpNodeProcessingInfo 定位最慢的 Node
如果自定义 Node 太慢 → 评估是否必要、能否先降分辨率再处理
② AWB/Stats 处理慢
检查 subsample 是否启用:
adb shell "echo logVerboseMask=0x04000200 >> /vendor/etc/camera/camxoverridesettings.txt"
adb shell "echo logInfoMask=0x04000200 >> /vendor/etc/camera/camxoverridesettings.txt"
adb reboot
在 logcat 中搜索 total_Cnt:
cnt = 768 → subsample 已启用
cnt = 3072 → subsample 未启用(需要优化)
③ AF 处理慢
减少 AF ROI 区域
将 singleWindowProcessingLevel: DYNAMIC → LOW
④ CPU 频率不够
检查 perflock 是否生效(KBA-190618011520)
使用 MPCTLV3_SCHED_UPMIGRATE/DOWNMIGRATE 绑定大核
必要时可解除 core7 隔离
⑤ Stats 各 Node 之间是否可以并行处理
检查 pipeline 拓扑,无依赖关系的 Node 可以并行
⑥ 自定义 Feature(实时 HDR/实时 Bokeh/实时美颜)
评估是否需要先降分辨率再处理
考虑 perflock boost CPU 频率是否生效
60fps → 帧间隔 16ms → 曝光时间不能超过 16ms
30fps → 帧间隔 33ms → 曝光时间不能超过 33ms
暗光下 AE 把 exposureTime 拉到 66ms:
[AEC] exposureTime=66000000
→ 帧率上限 = 1000/66 ≈ 15fps
取舍:
要流畅(30fps) → 限制最大曝光 33ms(提 ISO,噪点多)
要纯净 → 允许长曝光(帧率下降)
adb logcat -v threadtime | grep -E "ProcessCaptureRequest|ProcessCaptureResult"
# 同一条 requestId 的时间差 = 拍照延迟
# 也可以从 systrace 看 "HAL3:RequestTrace" 的 span 长度
logcat 时间线:
10:00:00.000 ProcessCaptureRequest() frame=42
10:00:00.100 AE converged
10:00:00.150 AF locked
10:00:00.200 CSLMessageHandler() requestID=42 ← ISP 处理完
10:00:00.600 ProcessCaptureResult() requestId=42 ← JPEG 编码完
瓶颈: JPEG 编码 400ms
验证: adb shell dumpsys media.camera | grep -A 5 "Pipeline"
如果只有 pipelineId=0 → Offline Pipeline 未启用
# Step 1: 在 camxoverridesettings.txt 中配置
traceGroupsEnable=0x10080 # 启用 UMD trace events
traceErrorEnable=TRUE
traceOutputEnable=0x10080
# Step 2: 启用 KMD trace
adb shell "echo 1 > /d/tracing/events/camera/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/options/record-tgid"
# Step 3: 抓取 systrace
systrace.py gfx camera view input sched freq video idle -b 20480 -t 5 -o trace.html
不同场景的 traceGroupsEnable 值:
0x10080 → 基本 Camera trace
0x40100C0 → 含 AWB 详细 trace
0x80100C0 → 含 AF 详细 trace
0x12080 → 含 multi-camera SAT trace
0xFFFFFFFF → 全部 trace(性能影响大,只在必要时用)
adb shell "/system/bin/simpleperf record -p <camera_provider_pid> \
--callgraph fp -o /data/misc/perf.data --duration 10"
adb shell "/system/bin/simpleperf report -i /data/misc/perf.data -g \
--full-callgraph > /data/misc/report_callgraph.txt"
adb pull /data/misc/report_callgraph.txt
在怀疑有耗时的代码位置添加 systrace tag:
#define ATRACE_TAG ATRACE_TAG_ALWAYS
ATRACE_BEGIN("CustomTag");
// 需要观测耗时的代码
ATRACE_END();
性能问题排查流程:
perf build → 关日志 → 确认 SOF → 检查 Node → 加 trace
关键工具:
traceGroupsEnable=0x10080 → systrace
dumpNodeProcessingInfo=1 → Node 耗时
enableFPSLog=1 → 实时帧率
SOF trace → Sensor 帧间隔
HAL3:RequestTrace → 帧生命周期
Simpleperf → CPU 热点
优化方向:
启动: 尽早 open + 延迟非实时 Session + I2C 优化
帧率: Node 并行 + AWB subsample + AF ROI + 绑定大核
拍照: Offline Pipeline + 硬件 JPEG 编码