0%
前言
- 如果某个App耗电量过大会导致手机发烫,会导致电池寿命变短,会导致用户体验不好。
- 本文给出Energy impact、Energy Log、sysdiagnose三种耗电检测方案,帮你找到耗电的代码,帮你提高用户体验
Energy impact
准备
- Edit Scheme->Profile->Build Configuration下拉设置为Debug,如果没有配置点击Instruments中的红色按钮运行iPhone的时候是会报错的
- Build Settings->Build Options->Debug Information Format->Debug->DWARF with dSYM File,如果没有配置检测结果显示地址而不是函数名。
- 设置完成后选择
Product->Profile
或快捷键cmd+ i
,再选对应的检测。
寻找耗电来源
- 连接真机->
command+R
运行项目->command+7
打开->点击Energy impact
查看电量情况,如图
Average Energy Impact
表示App的总体平均消耗电量评级。分为三部分,理想的状态时low、high状态。
- low的时候指向绿色区域
- high的时候指向黄色区域
- very high指向红色区域
Average Component Utilizationn
帮助我们快速了解各耗电部分的占比。当Average Energy Impact
为very high的状态时要找出下面哪部分占比大,进行相应的优化
Overhead
表示不是由App引起的耗电,可以忽略
Network
表示网络能耗占总能耗的百分比
CPU
表示CPU能耗占总能耗的百分比
GPU
表示GPU能耗占总能耗的百分比
Location
表示定位能耗占总能耗的百分比
Component Utilization
每根柱子代表每秒钟的耗电情况,每根柱子由不同颜色组成,不同颜色代表的意思参考Average Component Utilizationn
- 通过以上方法找出耗电占比大的某项(Network、CPU、GPU、Location),通过Profiler找出耗电详情,具体方法如下
- CPU点击
Time Profiler
按钮进入
- 网络点击
Network Profiler
按钮进入
- 定位点击
Location Profiler
按钮进入
- GPU点击
Product
->Profile
->Core Animation
按钮进入
Time Profiler
- 这里拿
Time Profiler
进行举例,点击Time Profiler
进入后,左下角点击Call Tree
进行过滤
Separate by Thread
按线程进行分析,便于找到消耗资源大的线程。
Invert Call Tree
反向输出调用树,把调用层级反向输出,更容易找到最耗时的操作。
Hide System Libraries
隐藏系统库文件,只显示自己的代码调用。
Top Functions
找到最耗时的函数或方法。
- 在调用树的表格中,按权重(weight)展开,要干掉的就是权重大的,耗时间的。
- 接着展开Main Thread(其他线程的耗时,相比主线程的,可忽略 ), 按住Option键,点击 Main Thread左边的小三角,可以一下子展开很多。
- 找到最耗时的方法点击两次进入详情,这个时候可以优化了
Energy Log
- 方式一,适用于测试人员,测试时不需要把手机连接到Xcode,测试完成后在连接到Xcode查看数据
- iPhone->设置->开发者->Loggin->Start Recording
- 然后打开要测试的App随意点击,Stop Recording
- Xcode->Open Developer Tool->Instruments->Energy Log
- 选择要测试的设备和App
- 左上角File->Import Logged Data From Device
- 方式二,适用于开发人员,测试时需要把手机连接到Xcode
- 双击打开EnergyLog直接点击红色圆点运行程序
- App启动后,在里面进行各种操作
- 点击黑色方块停止检测,这个时候可以看到数据,如果正在检测是看不到数据的
- 使用说明
- 可以看到CPU活动比例,网络活动比例,亮度状态,手机睡眠状态,手机连接蓝牙状态,手机连接wifi状态,手机GPS状态这次都是手机耗电的构成部分。
- level值为0–20,值越大表示越耗电。1/20表示运行该app电池生命会有20个小时;20/20表示运行该app电池电量仅有1小时生命
- WWDC2018里介绍了用
Energy Log
来查CPU耗电,当前台三分钟或后台一分钟CPU线程连续占用80%以上就判定为耗电,同时记录耗电线程堆栈供分析
sysdiagnose
电量单位
- 电压
- 电压以mV计,通过硬件测得,是计算其他数据的基础
- iPhone工作时,电压几乎一直恒定在4V左右,测试过程中出现过的最高电压是4.3V。
- 当电池剩余电量越少时,电压值会变得越小,但波动不大。
- 电压过小时,可能会引起手机直接关机,这也是为什么有时还有20%电量,但手机却开不了机了。
- 新的电池,电压波动会小一些,越是老化,电压波动可能越大。
- 电压这个值能用来判断当前电池的健康度。
- 电流
- 电流以mA计,直接通过硬件测得,是计算其他数据的基础,
- iPhone工作时,电流一般在1mA到700mA之间。超过500mA电池很容易发热。
- 温度
- 通过硬件接口获得,可以作为一个参考值
- 测试过程中出现的最高温度是37度,能明显感觉到发热了。
- mAh(毫安时):
- 电池容量的计量单位,实际就是电池中可以释放为外部使用的电子的总数,需要乘上当前的电压(6P是4v)才是真正的能量。
- 公式
- W=UIt=Pt,P=UI
- W表示电工单位为J,U表示电压,I表示电流,t表示时间单位为s或h,P表示功率单位为W
- 电功=电压×电流×时间=功率×时间
- P=UI=W/t
日志
- 日志记录对电源使用没有影响,但是如果启用数天而不进行同步,它确实会累积磁盘空间。 为了避免这种磁盘使用情况的积累,一旦提供了所需的诊断信息,请关闭日志记录。
- 电池日志文件以
powerlog_
开头和以.PLSQL
或.PLSQL.gz
结尾
- 启用日志记录
- 去苹果开发者网站找到
Battery Lift
下载profile(需要登录开发者账号)
- 下载完成后通过隔空投送发到测试手机上安装。
- 不要重启手机,等待10到30分钟,手机连上电脑,通过 iTunes 同步到电脑上。
- 日志位置
- iOS: 设置 > 隐私 > 分析 > 分析数据 > (定位sysdiagnose文件,使用隔空投送发送到macOS上面).
- macOS: ~/Library/Logs/CrashReporter/MobileDevice/[Your_Device_Name]/
- Windows 10:
1 2
| C:\Users\USERID\AppData\Local\Packages\AppleInc.iTunes_devicename\LocalCache\Roaming\Apple Computer\Logs\CrashReporter\MobileDevice\[Your_Device_Name]/DiagnosticLogs/
|
- 禁用日志记录
- Launch Settings.
- Tap General > Profiles.
- Tap appropriate profile.
- Tap Remove and enter passcode if asked.
- Restart device.
- 找到
powerlog_2020-01-06-2020-01-09_0AF1E160.PLSQL
,使用SQLPro for SQLite
或Navicat Premius
打开,发现里面有几百张表,所有的电量数据都在里面,主要的几张表的意思如下
- PLBatteryAgent_EventBackward_Battery:整台机器的电量数据,包含电流、电压、温度等,每20秒左右一条数据
- PLBatteryAgent_EventBackward_BatteryUI:电量百分比数据,大于每300秒一条数据
- PLIOReportAgent_EventBackward_EneryModel: 整机的详细电量数据。包含 CPU\GPU\DRAM\ISP 等关键信息。每半小时到一小时一条数据。
- PLAccountingOperator_EventNone_Nodes:App结点信息,每个APP对应唯一的结点号。用来确定手机内具体哪个 App。
- PLApplicationAgent_EventForward_Application:App运行信息,记录每个App在哪个时间段以什么状态运行
- PLAppTimeService_Aggregate_AppRunTime:APP的运行时长统计,每个运行过的APP,一小时一条数据
- PLAccountingOperator_Aggregate_RootNodeEnergy: APP的电量详细数据,记录每个APP 的CPU\GPU\DRAM\ISP 等的耗电信息。一小时更新一次数据。
- RootNodeID:6 isp
- RootNodeID:52 apsocbase
- RootNodeID:10 display
- RootNodeID:11 wifi data
- RootNodeID:8 GPU
- RootNodeID:4 venc
- RootNodeID:2 cpu
- RootNodeID:7 restofsoc
测试方式
- 先去
PLAccountingOperator_EventNone_Nodes
通过BundleID找到我们要测试的App的I我们要测试微信,其实可以发现,表中对应的Name字段就是BundleID,微信对应的ID为10521。
- 得到每个App的唯一标识后,我们就可以去
PLAccountingOperator_Aggregate_RootNodeEnergy
表里看电量消耗数据了:1
| SELECT *,DATETIME(timestamp,'unixepoch','localtime') from PLAccountingOperator_Aggregate_RootNodeEnergy WHERE NodeID=10521 ORDER BY timestamp DESC;
|
- 表中的
Energy
就是对应消耗的电量了,这里的单位在iOS9是mAh,iOS9及以上应该是 1/1000 mAh。比方测试2020-01-08 17:00:00
这个时间耗电量,可以执行SQL语句计算出来。这个耗电量为3182 / 1000 = 3.182
mAh1
| SELECT SUM(Energy) from PLAccountingOperator_Aggregate_RootNodeEnergy WHERE NodeID=10521 AND timestamp=1578474000 ORDER BY timestamp DESC;
|
- 如果想知道运行这个App这段时间内的温度,可以
PLBatteryAgent_EventBackward_Battery
表中获取,但是因为该表的数据是整个机器的,所以我们需要根据对应的时间节点来观察数据: