前言
当我们sdk集成到业务方app时,经常会收到诸如“集成后app运行发热发烫明显”、“手机电池百分比较之前版本下降明显”等反馈,面对这类由于集成后带来的能耗问题或质疑,比较好的一个解决方法是在准入规则中引入能耗测试,并制定出能耗数据标准,然后用测试数据比对该标准来判断该次迭代是否会带来能耗方面的问题。
工作时能耗状态
- Idle:表示app处于休眠状态,几乎不使用电量。
- Active:表示app处于工作状态,用电量比较高,图中的第二个 active的耗电高于第一个,这是由于app所做的工作类型不同而导致的。
- Overhead:表示调起硬件来支持app功能所消耗的电量,是支持硬件工作必要的电量消耗,另外我们发现如果两个任务间间隔时间很短时候,app由于不及时释放资源也会导致fixed cost维持在一个比较高的水平
- Fixed cost:横线以下区域代表固定开销
- Dynamic cost:横线以上区域代表动态开销
基于上述应用的工作状态,我们对以下几个主要到消耗点进行关注。
主要能耗点
Display:app内容每次更新到屏幕上都需要消耗电能处理像素信息,主要体现UI的展示和更新上,相对SDK而言这部分影响较小。
CPU:主要用于app/sdk终端数据处理,也是能耗中占比较大的部分。
Network:包括wifi、4G等网络传输,当app/sdk频繁进行网络请求时,蜂窝网络或Wi-Fi组件就会占用较多等能耗,所以应减少数据传输,合并网络请求,适当的网络延时。
GPS:基于位置服务进行定位,定位精度越高或时间越长,消耗电量也就越多。
Sensor & Bluetooth:各类传感器的开启也会对能耗造成一定的影响,蓝牙活动频度太高也会消耗电能,应该尽量减少数据轮询等操作。
大致了解了可能影响我们APP能耗的主要方面后,我们如何对其进行量化的测试呢?
测试方法
测试工具:
Sysdiagnose
许多工具可以用来做iOS的能耗测试,如:Energy Impact,Instrument Energy Log等,其中Energy Impact可以通过实时展示电量消耗来直观的显示能耗,但是缺点是颗粒度较大,需要结合其他工具来进行更细节的分析,Energy Log是xcode的集成组件,可以实时的针对APP进行各个维度(如energy,cpu, network,Wi-Fi等的监控),但其与Energy Impact类似,只能查看能耗的整体水平,无精准的数据输出,且需要手机与终端连接(可网络连接),这样就无法在有源的状态下判别实际消耗。
这里我们使用苹果内置的iOS诊断工具Sysdiagnose来进行测试:
测试实例:通过对比sdk集成前后同一版本app中能耗的差值进行分析,估算出sdk的能耗
step:
- 手机放电状态下关闭其他app,前台运行集成sdk的app和未集成sdk的app各两小时,并记录开始和结束时间(测试1中app未集成sdk,测试2中app集成并开启了sdk)
- 测试完成并等待一小时后,开启手机上的“分析”功能,待分析结束使用iTunes同步手机并拷贝sysdiagnose 文件(/Users/eleme/Library/Logs/CrashReporter/MobileDevice/iPhone wb/DiagnosticLogs/sysdiagnose/xxx.tar.gz)到本地目录并解压
- 使用DB browser for SQLlite工具打开powerlog目录下对应的powerlog_xxxx.PLSQL文件
- 数据库中有许多表格,具体可参考苹果官方文档,我们主要查询以下表项:
表名 概述 PLBatteryAgent_EventBackward_Battery_UI 记录剩余电量百分比 PLAccountingOperator_EventNone_Nodes 各个硬件对应的 Node ID,以及各个 App 的对应的 Node ID PLAccountingOperator_Aggregate_RootNodeEnergy App在单位时间内各硬件对能耗 PLBatteryAgent_EventBackward_Battery 整体耗电量和温度变化 - 在PLAccountingOperator_EventNone_Nodes中通过查找AppNodeName获取测试我们需要测试app的NodeID,并使用这个ID查询PLAccountingOperator_Aggregate_RootNodeEnergy中各个硬件的消耗:
- select datetime(timestamp, 'unixepoch','localtime')as time,timeInterval,Energy,NodeID,RootNodeID as Hardware from PLAccountingOperator_Aggregate_RootNodeEnergy where NodeID=(SELECT ID FROM PLAccountingOperator_EventNone_Nodes WHERE name = $appName) order by time DESC;
- 测试1
- 测试2
- 我们可以从两次测试的能耗差值估算我们sdk的消耗,并从开启sdk的测试中得到CPU, DRAM, Network, GPS等硬件所占用总能耗的百分比,从对比中我们可以看到开启sdk后,CPU,网络,GPS等硬件的能耗上升略微显著
- 改进优化
- 从上面的结果看,开启sdk后网络传输、cpu和定位消耗的资源会略有升高
- 我们可以在不影响业务的情况下对网络传输进行优化,如对数据进行压缩、合并网络请求或降低传输频率等
- 适当降低gps定位精度,在不需要时关闭gps调用等
后记
- 过程中的问题:
- 首先对于不同的终端,使用该测试方法获取的数据实际起始时间可能会因设备的不同(数据表中的timestamp值)而存在差异,所以我们如果需要以小时为单位测试时,最好先获取一次该终端的起始时间
- 测试结束后,终端需要等待至少一小时后才能使用分析工具去获取数据,测试周期略长,数据量较大
- 单个小时内的测试数据可能存在一定的差异,因此建议可以将测试时间拉长至2-3小时来获取更精确的测试结果
- 对于不同型号的终端,传感器的硬件 nodeID可能是不相同的,如iPhone11中56(DisplayDynamic),57(Socdisplay),但在iPhone7或8中是没有的,在横向比较时可能会存在差异。