24. 功耗基线管理:建立功耗基线、基线对比方法、功耗回归预防
功耗优化做到一定程度,你会发现一个尴尬的问题:改了一版代码,功耗到底是变好了还是变差了?
我见过太多团队,优化做了几个月,结果一问基线是多少,没人说得清。大家凭感觉说“好像省电了”,但拿不出数据。这其实很危险——你很可能在“优化”的过程中,反而引入了功耗回归。
所以这一章,我们来聊聊功耗基线管理。说白了,就是给功耗上个“锚点”,让每一次改动都有据可查。
24.1 什么是功耗基线?为什么它如此重要?
功耗基线,就是你在某个特定版本、特定场景下测得的功耗数据。它像一个“标尺”,用来衡量后续所有改动的影响。
我个人习惯把基线分为三层:
- 版本基线:每个正式发布版本(如V1.0、V2.0)的功耗数据
- 场景基线:特定场景下的功耗数据(如相机预览、录像、HDR拍照)
- 模块基线:某个子模块的功耗数据(如ISP、GPU、DSP)
没有基线,你根本不知道优化有没有效果。更可怕的是——你可能在“优化”的路上越走越远,功耗反而越来越差。
核心观点:基线不是一次性的,它是持续迭代的。每次发布新版本,基线都要更新。
24.2 如何建立功耗基线?
建立基线,听起来高大上,其实步骤很清晰。我总结了一个“四步法”:
第一步:确定测试场景
相机场景太多了。你不能把所有场景都测一遍,那会累死人。我建议选几个“黄金场景”:
- 相机冷启动:从点击图标到第一帧预览显示
- 预览场景:30fps预览,持续5分钟
- 录像场景:1080P@30fps录像,持续10分钟
- 拍照场景:连拍20张,间隔1秒
- 待机场景:相机后台挂起,持续30分钟
每个场景测3次,取平均值。为什么是3次?因为功耗数据波动很大,一次不准。
第二步:统一测试环境
这一点我吃过亏。有一次基线数据波动很大,查了半天,发现是测试时屏幕亮度不一样。嗯,从那以后,我定了个规矩:
- 屏幕亮度固定为200nit
- WiFi/BT关闭,SIM卡插入但无业务
- 手机温度控制在25±2°C
- 使用同一台测试设备(不要换机器)
- 测试前充满电,静置10分钟
注意:环境温度对功耗影响巨大。夏天和冬天的基线数据不能直接对比。我建议在恒温箱里测,或者至少记录环境温度。
第三步:采集数据
数据采集工具,我推荐用这三件套:
| 工具 | 用途 | 精度 |
|---|---|---|
| Monsoon Power Monitor | 整机电流采集 | ±1mA |
| Perfetto | 模块级功耗分析 | ±5% |
| BatteryStats | 软件级功耗统计 | ±10% |
我个人习惯用Monsoon做基线,因为它最准。Perfetto用来做模块级分析,BatteryStats用来做快速验证。
第四步:记录基线
基线数据要记录到文档里,格式要统一。我常用的模板是这样的:
# 功耗基线报告 - Camera V2.1
## 测试信息
- 设备:Pixel 6 Pro
- 版本:V2.1 (Build 20240301)
- 测试日期:2024-03-05
- 环境温度:25°C
## 基线数据
| 场景 | 平均电流(mA) | 峰值电流(mA) | 功耗(mW) |
|------|-------------|-------------|---------|
| 冷启动 | 580 | 1200 | 2146 |
| 预览 | 420 | 650 | 1554 |
| 录像 | 680 | 850 | 2516 |
| 拍照 | 750 | 1100 | 2775 |
| 待机 | 15 | 30 | 55.5 |
## 备注
- 预览场景使用默认相机APP,后置摄像头
- 录像场景使用1080P@30fps,H.264编码
24.3 基线对比方法
基线建好了,怎么对比?直接看数字大小?没那么简单。
方法一:绝对值对比
最简单的方法。新版本测一遍,和基线比绝对值。比如基线预览是420mA,新版本是400mA,那就是优化了20mA。
但这里有个坑:功耗数据有波动。你测3次,可能得到410、420、430。所以对比时,要看置信区间。我一般用这个规则:
- 差异 < 5%:视为无变化
- 差异 5%-10%:需要复测确认
- 差异 > 10%:确认有变化
方法二:归一化对比
有时候场景不完全一致,比如录像时长不同。这时候需要归一化。我常用的归一化方式:
- 按时间归一化:总功耗 / 测试时长,得到平均功耗
- 按帧数归一化:总功耗 / 总帧数,得到每帧功耗
- 按分辨率归一化:总功耗 / 像素数,得到每像素功耗
举个例子:
基线:录像10分钟,总功耗1500mAh,平均功耗150mAh/min
新版本:录像8分钟,总功耗1280mAh,平均功耗160mAh/min
结论:新版本功耗反而高了6.7%!
你看,如果不归一化,只看总功耗(1280 vs 1500),你会以为优化了。但归一化后,真相大白。
方法三:趋势对比
单个版本对比不够,要看趋势。我习惯画一个“功耗趋势图”,横轴是版本号,纵轴是功耗值。这样一眼就能看出功耗是在变好还是变差。
你看这张图,V2.1版本出现了明显的功耗回归。如果没有趋势图,你可能根本不会注意到。
24.4 功耗回归预防
功耗回归,说白了就是“改坏了”。我见过太多案例:
- 加了一个新功能,功耗涨了10%
- 修了一个bug,结果引入了新的功耗问题
- 升级了SDK版本,相机功耗直接翻倍
怎么预防?我总结了三个“防线”:
第一道防线:代码审查
代码审查时,加一个“功耗检查项”。我常用的检查清单:
- 是否新增了不必要的唤醒锁?
- 是否在预览路径中增加了耗时操作?
- 是否关闭了不再使用的硬件模块?
- 是否使用了高效的编码格式?
- 是否有内存泄漏导致GC频繁?
我曾经在代码审查中发现一个同事在预览回调里做了图像处理,每次回调都申请新内存。嗯,这直接导致GC频率从1次/分钟变成了10次/分钟,功耗涨了8%。
第二道防线:自动化测试
手动测试太慢了。我建议把功耗测试集成到CI/CD流水线中。每次提交代码,自动跑一遍基线场景,如果功耗超过阈值,自动告警。
阈值怎么设?我一般用这个规则:
- 警告阈值:基线 + 5%
- 失败阈值:基线 + 10%
超过警告阈值,发邮件通知。超过失败阈值,直接阻断合并。
小技巧:自动化测试不要跑所有场景,太耗时。选3个核心场景就够了:预览、录像、待机。每个场景跑2分钟,整条流水线控制在10分钟以内。
第三道防线:回归分析
如果发现功耗回归,怎么定位?我习惯用“二分法”:
- 找到回归版本和上一个正常版本
- 列出两个版本之间的所有代码变更
- 逐个回退变更,测试功耗
- 找到罪魁祸首
举个例子:
正常版本:V2.0,预览功耗420mA
回归版本:V2.1,预览功耗440mA
变更列表:
1. 升级了ISP驱动
2. 增加了美颜滤镜
3. 修改了预览帧率控制
回退测试:
- 回退ISP驱动 → 功耗仍为440mA(排除)
- 回退美颜滤镜 → 功耗降为420mA(找到!)
你看,二分法很有效。但要注意,有时候多个变更叠加才会导致回归,单个回退可能看不出来。这时候需要组合测试。
24.5 基线管理的“最佳实践”
最后,分享几个我踩过的坑和总结的经验:
经验一:基线数据要“可复现”
记录基线时,一定要把测试条件写清楚。我曾经看到一份基线报告,只写了“预览功耗420mA”,其他什么都没写。后来想复现,发现根本不知道当时用的什么相机APP、什么分辨率、什么帧率。这基线等于白建。
经验二:基线不是“死”的
基线要定期更新。我建议每个大版本更新一次基线。如果中间有重大改动(比如换了ISP芯片),也要立即更新基线。
经验三:关注“异常值”
有时候基线数据里会出现一个异常高的值。不要直接忽略,要查清楚原因。可能是测试环境有问题,也可能是代码有bug。我曾经遇到过一次,基线里有个异常值,后来发现是测试时手机在充电。嗯,这种低级错误,谁都会犯。
好了,这一章的内容就到这里。功耗基线管理,说白了就是“用数据说话”。没有基线,你所有的优化都是盲人摸象。有了基线,你才能知道每一步是前进还是后退。
记住:基线不是终点,而是起点。每一次优化,都要以基线为参照,以数据为证据。这样,你的功耗优化之路才会越走越稳。
最后一个小建议:把基线管理做成一个“仪式”。每次发布版本前,团队一起看基线数据,讨论功耗变化。这不仅能发现问题,还能培养团队的功耗意识。