耗电量不仅是衡量应用性能表现的一个重要指标,同时也是用户体验的重要组成部分。要做好⼀款APP,不仅仅是实现功能那么简单,我们需要考虑很多性能指标,让用户用的更爽。在开发过程中,要充分考虑到各项性能指标,比如定位精度,更高的精度,往往意味着更高的能耗,因此要平衡好精度和功耗,避免我们的APP过多的电量消耗。
耗电量基本概念
1.What Is Energy?
- Idle状态说明 app 处于休眠状态,几乎不使用电量。
- Active状态说明 app 处于前台工作状态,用电量⽐较高,我们可以看到图中的第二个Active的耗电量远高于第一个,这主要是因为 app 实际所做的工作类型不同导致的。
- Overhead 指的是调起硬件来支持 app 功能所消耗的电量。注意:如果你的 app 就算只做了一点事, Overhead所带来的电量消耗都是一点不会减少的!
- 图中横线以下所包区域是固定开销(Fixed Cost),横线以上区域是动态开销(Dvnamic cost)。
2.耗电大户
1)网络
网络通信时,蜂窝数据和Wi-Fi等元器件开始工作就会消耗电能。分批传输、减少传输、压缩数据、恰当地处理错误,你的app省电效果就会很显著。
2)定位
a pp为了记录用户的活动或者提供基于位置的服务会进行定位。 定位精度越高,定位时间越长,消耗电量也就越多。 所以app应该尽量降低定位精度、缩短定位时间。 不需要位置信息之后立即停止定位。
3)CPU
CPU是电能消耗大户,高CPU使⽤量会迅速消耗掉用户的电池电量。 app做的每件事几乎都需要用CPU,所以使⽤CPU要精打细算,真正有需要时通过分批、定时、有序地执行任务。
4)GPU
app内容每次更新到屏幕上都需要消耗电能处理像素信息。动画和视频格外耗电。不经意的或者不必要的内容更新同样会消耗电能,所以UI不可见时,应该避免更新其内容。
5) 传感器和蓝⽛
长时间用不上加速度计、陀螺仪、磁力计等设备的动作数据时,应该停止更新数据,不然也会浪费电能。应按需获取,用完即停。蓝⽛活 动频度太高会消耗电能,应该尽量分批、减少数据轮询等操作。
耗电量检测方案
1.Energy Impact
1.1 Average energy Imapct
指针所指向的半圆环分为三部分,代表的是 app 的总体上的平均消耗电量评级,low(绿色区域)、high (黄色区域)、very high(红色区域)通过这张图我们可以大致了解app 电量的使用情况。 理想的状态是 app 处于 low、high 状态。 但是通常情况下,如果我们进行过优化,app 会处于 high、甚至very high 状态。 我们需要更深入地知道究竟哪一部分的功能导致耗电量大涨 。
1.2 Average Componet Utilization
饼状图展示的是Overhead 、CPU 、NetWork、Location 、GPU 各部分耗电量的占比,通过这个占比,我们可以分析各部分耗电量是否较高。
1.3 Energy Impact
在柱状图中每根柱子代表了每秒钟的耗电情况。 每根柱子都由不同颜色的矩形块堆叠而成。 依次是 Overhead(红色)、CPU(蓝色)、网络(深黄)、定位(淡黄)、GPU(绿色)、后台(深灰)、前台(淡灰)、Suspend(白色) 。
1.4 总结
在使用Energy Impact的过程中,首先可以观察 Average energy Imapct 了解app的整体耗电量情况,处在什么位置,对整体有个大概的了解,然后通过 Average Componet Utilization 来观察app整体耗电量中,具体哪一部分占比较高,最后使用Energy Impact进行实时分析,分析页面各部分消耗是否是必要的,比如某个页面只在进入的时候需要获取经纬度,后面不需要实时获取经纬度,那么在进入页面获取经纬度以后,就要将定位关闭,以减少电量消耗。
优点:实时性高、数据分析可以通过图形直观展示、可以获取`Overhead(红色)、CPU(蓝色)、网络(深黄)、定位(淡黄)、GPU(绿色)、后台(深灰)、前台(淡灰)、Suspend(白色)等数据和各部分数据占比。
缺点:颗粒度较大,想做详细的分析,需要借助其它工具。比如针对CPU的消耗情况,可以通过 Time Profiler来进行分析,分析具体哪部分代码消耗较多,使用Network Profiler来分析网络的消耗情况,使用Location Profiler来分析定位的情况,详细获取各部分数据,找到电量的消耗点。
2.Energy Log
2.1 Energy Log使用
设置路径:开发者 -> Logging -> Energy -> Start Recording -> Stop Recording。
首先找到开发者,点击进入,找到Logging选项,如下图:
然后点击进入Logging选项、进入新页面,打开Energy开关,同时点击Start Recording,此时开始记录电量消耗情况,,这时你可以选择想要测试的app,在测试完毕后,点击Stop Recording,关闭电量记录功能,如下图:
最后,将手机连接到电脑,导出设备中的电量记录数据,在Energy Log中,可以看到详细的电量消耗数据,如下图:
2.2 Energy Log组成
- Energy Usaqe Loq代表能耗消耗级别,有 0 到 20 的级别,表示应用在任何给定时间使用了多少电量,值越大表示越耗电。可以用来分析app的总体能耗。
- CPU Activity Log 代表cpu能源消耗,包括 : Foreground app Activity 、Graphics Activity、 Media Activity 、Other Activity 。
- Network Activity Log 代表网络能源消耗,包括 : Cellular in 、Cellular out、Wi-Fi In 、Wi-Fi Out 。
- Display Brightness Log代表屏幕消耗。
- Sleep/Wake log代表仪器捕获有关设备当前状态的信息。
- Bluetooth On/Off Loq代表蓝牙开关状态。
- Wi-Fi On/Off Log代表Wi-Fi开关状态。
- GPS On/Off Log代表GPS开关状态。
2.3 总结
在使用Energy Log过程中,可以通过横向比较各个维度的数据,来分析各部分的能源消耗,分析能耗的使用情况,更合理的使用⼿机电量。
优点:Energy Log可以测试自⼰app和别人app的电量消耗,有各个上面维度的详细数据,比如:某个时刻的cpu使用情况、定位使用情况,可以关联CPU、定位、总能耗消耗等数据,通过这些数据,分析使用是否合理。
缺点:Energy Log只能看整体能耗的水平,同时由于log不是实时的,要具体确定某个页面或者某个路径的能耗情况,需要⾃⼰测试的时候记录一下,只能大概对照,而且不能输出精准数据。
3.Sysdiagnose
Sysdiagnose是用来诊断系统问题的工具,它包括了过去几天⾥,系统整体的详细功耗情况、各个App在各个硬件上的耗电情况,温度、 电流等一系列详细的数据。这些数据最终会存储在数据库中,数据库中包含多张数据表,比如在iOS12的系统中,有多达406张表。
3.1 配置
苹果在《电池诊断日志的导出指南 》中详细说明了导出日志的步骤。 这⾥简要说明一下大概的步骤。
- 首先在你的测试机上,安装电量分析的profile,安装完成后,iOS 才会记录最详细的功耗数据,并开放读取(推荐下载后用Airdrop 发送到手机上安装);
- 第二步,连接上 iTunes 并同步,这时 iTunes 就会自动把手机上的功耗的历史记录拷贝到电脑上;
- 第三步,断开设备,运⾏你的 App,这时设备已经在记录功耗信息,记得留意你运行 App 时的时间,因为稍后要和数据库中的时间戳进行匹配;
- 第四步,再次连接上 iTunes 并同步,这时 iTunes 就会自动把手机上的详细功耗记录拷贝到电脑上。
3.2 获取数据
到 iTunes 的同步文件夹( ~/Library/Logs/CrashReporter/MobileDevice/你的手机名/)下,找到以Powerlog_开头,后缀是.PLSQL或者.PLSQL.gz的几个文件,这些就是记录了所有功耗信息的数据库文件了,可以使用DB Browser for SQLite来打数据库。
3.3 分析数据
数据库中有多张表格,这些表格的具体用途,苹果没有详细说明,下⾯是一些开发者总结的部分表格信息。
我们可以根据上面的表格,来分析耗电情况,比如:
- PLBatteryAgentEventBackwardBattery_UI 可以分析剩余电量曲线
- PLBatteryAgentEventBackwardBattery 可以分析整体耗电量和温度变化
- PLAccountingOperatorAggregateRootNodeEnergy 和 PLAccountingOperatorEventNoneNodes 两张表,可以得到某个 Bundle ID 对应的 App 在各个硬件上的耗电情况。
3.4 总结
Sysdiagnose是一个可以详细获取各个维度数据的工具,具体到某个app、某段时间、某个硬件的具体能源消耗,可以使用这个工具,进 行app的不同场景的能耗数据对比、竞品app的能耗数据分析和对比,十分精确。
优点: 可以精确获取各个维度的能耗消耗数据,包括:isp 、apsocbase 、dispaly 、WiFi Data 、GPU 、CPU 、restofsoc 、GPS 、DRAM 等详细数据。 通过这些数据,可以分析某个app的某段时间,各个维度的能耗数据,这个 数据十分精确。
缺点:数据不能实时获取,部分数据需要等待一个小时才能获取,数据量较大,没有官方文档指导,需要自己分析各个表中的数据含义。
4.MetricsKit
WWDC19 Session 417, Improving Battery Life and Performance,苹果推出的三项性能监控工具分别是:
- XCTest Metrics (开发和测试阶段)
- MetricsKit (内测阶段和线上阶段)
- Xcode Metrics Organizer (线上阶段)
苹果推出的性能指标监测工具可以分为两大类,分别是耗电量统计和性能监测。
4.1 Battery Metrics
耗电量的指标可以分为几种,Metrics 可以分别进行统计,可以统计的几个耗电量大户分别是:
- Processing,包括:CPU time, GPU time, etc.这些指标可以来度量和理解 App 的复杂度,它们可以用来比对各个功能的算法效率, 发现无效的渲染等。
- Location,包括:Cumulative usage time, bakcground time, etc.可以用来了解定位的使用情况。
- Display 指:Average Pixel Luminance (简称 APL,平均像素亮度,即每个像素的平均亮度),在 X/XS ⼿手机上,OLED 屏幕显示的 UI 的颜色直接影响到能耗。
- Networking 包括:Upload and download bytes, connectivity, etc。尽可能优化网络使用,因为它是一项高能耗的任务。
- Accessories (蓝牙)
- Multimedia
- Camera
4.2 Performance Metrics
性能指标包括以下几项:
- Hangs
- Disk
- Application Launch
- Memory
- Custom Intervals
苹果着重介绍了前四个。
1)Hang Metrics
Hang Metrics 就是我们常说的卡顿监测 ANR,它可以用来:
- 查找哪些地方的任务可以移到后台线程
- 利用各种 dispatches 和 queues 来减少卡顿的概率
2)Disk Metrics
这个指标记录的是磁盘逻辑写入,它用来度量磁盘使⽤情况,可以用来:
- 定位多余的磁盘写入检
- 查合并策略
3)Application Launch Metrics
可以⽤来度量 App 启动或恢复所消耗的时间。
- 了解启动时的耗时因素,例如数据库加载对启动耗时的影响有多大
- 查看启动和恢复这两种路径下的不同耗时
4)Memory Metrics
内存的管理很重要,它也可以影响到应用的启动速度,以及在后台时,被终止的可能性。 Memory Metrics 用于查看平均内存占用,以及峰值内存占⽤。 它可以用来检测内存的使用情况,例如:
- 定位难以复现的内存泄漏
- 减少应⽤挂起后的平均内存占用(有助于推迟应用被终止的时间)
优化建议
1.网络
1.1 缩减网络请求
1)减少、压缩网络数据。 可以降低上传或下载的多媒体内容质量和尺寸等。
2)使用缓存,不要重复下载相同的数据。
3)使⽤断点续传,否则网络不稳定时可能多次传输相同的内容。
4)网络不可用时不要尝试执行网络请求,尽量只在Wi-Fi情况下联网。
5)让用户可以取消长时间运行或者速度很慢的网络操作,设置合适的超时时间。
6)网络请求失败后用SCNetworkReachability的通知监测网络状态,网络可用后再重试。
1.2 延迟联网
1)分批传输。 比如,下载视频流时,不要传输很小的数据包,直接下载整个文件或者一大块一大块地下载。 如果提供广告,一次性多下载一些,然后再慢慢展示。 如果要从服务器下载电子邮件,一次下载多条,不要一条一条地下载。
2)网络操作能推迟就推迟。如果通过HTTP上传、下载数据,建议使用NSURLSession中的后台会话,这样系统可以针对整个设备所有的网络操作优化功耗。将可以推迟的操作尽量推迟到设备充电状态并且连接Wi-Fi时进行,比如同步和备份工作。
2.定位
1)如果你的app只是需要快速确定一下用户的位置,最好⽤CLLocationManager的requestLocation (iOS9引⼊入)方法。 定位完成之后会 自动让硬件断电。
2)除非是在导航的时候,app大部分时间不需要实时更新,降低位置的更新频率。
3)尽量降低定位精度。iOS设备默认采用最⾼精度定位,如果你的app不是确实需要米级的位置信息,不要用最高精度(kCLLocationAccuracyBest)或10米左右的精度(kCLLocationAccuracyNearestTenMeters)。一般来说Core Location提供的精度比你设置的要好,比如你设置为3公里左右的精度,可能会收到100米左右的精度信息。
4)如果定位精度一直达不到设置的精度时,停止更新位置,稍后再试。
5)需要后台更新位置时,尽量把pausesLocationUpdatesAutomatically设为YES,如果用户不太可能移动的时候系统会自动暂停位置更 新。
6)后台定位时延时更新位置。如果要做一个健身类的软件追踪用户徒步的距离,可以等用户移动一段距离或者过一段时间之后再更新位置,这样可以让系统优化能耗。
3.CPU
3.1 尽量减少计时器使用
使用计时器时,设置一个合适的超时,不再需要时及时关闭重复性定时器。用事件通知代替定时器。有些app用定时器监控文件内容、 网络或者其他状态的变化,这会导致CPU无法进入闲置状态而增加功耗。
3.2 减少后台工作
实现UIApplicationDelegate中的方法,应用进入后台前做好暂停任务,保存数据等工作。如果确实需要完成用户执行的一些任务,应该调 用UIApplicationDelegate中的beginBackgroundTaskWithExpirationHandler: 方法,这样后台任务可以继续执行几分钟。 任务执行完毕后 一定要调用endBackgroundTask:方法,不要等着系统强行挂起进程。
3.3 用QoS分级有序工作
多个app和众多操作需要共享CPU、缓存、网络等资源,为了保持高效,系统需要根据不同任务的优先级智能地管理这些工作。 比如更新UI这种重要的事需要多分配资源,而一些后台任务可以延迟一些执行。 服务质量(quality of service, 以下简称QoS, iOS8引⼊入)级别可以通过NSOperation, NSOperationQueue, NSThread objects, dispatch queues, 和pthreads (POSIX threads)指定工作的优先级。
3.4 优化I/O访问
app每次执行I/O任务,比如写⽂件,会导致系统退出闲置模式。 而且写入缓存格外耗电。 通过下列方法可以提高能效、改善app性能。
1)减小写入数据。 数据有变化再写文件,尽量把多个更改攒到一起一次性写入。 如果只有几个字节的数据改变,不要把整个文件重新写入一次。 如果你的app经常要修改大⽂件⾥很少的内容,可以考虑用数据库存储这些数据。
2)避免访问存储频度太高。如果app要存储状态信息,要等到状态信息有变化时再写入。尽量分批修改,不要频繁地写入这些小变动。
3)尽量顺序读写数据。在文件中跳转位置会消耗一些时间。
4)尽量从⽂件读写大数据块,一次读取太多数据可能会引发一些问题。比如,读取一个32M⽂件的全部内容可能会在读取完成前触发内容分页。
5)读写大量重要数据时,考虑用dispatchio,其提供了基于异步操作文件I/O的API。用dispatchio系统会优化磁盘访问。
6)如果你的数据由随机访问的结构化内容组成,建议将其存储在数据库中,可以使用SQLite或CoreData访问。特别是需要操作的内容可能增长到超过几兆的时候。
7)了解系统如何缓存文件、如何优化缓存的使用。如果你不打算多次引用某些数据,不要⾃己缓存数据。
4.GPU
1)减少app使用的视图数量。
2)少用运算获得圆角,不论view.maskToBounds还是layer.clipToBounds都会有很大的资源开销。
3)尽量少用透明或半透明,会产⽣额外的运算。
4)执行动画时不要修改帧率。比如,你的app帧率是60fps,整个动画就保持这个帧率不要变。
5)视频播放时,app尽量不要在全屏视频上添加额外的图层(即使是隐藏的图层)。
5
优化通知
1)尽量用本地通知(local notification),如果你的app不依赖外部数据,而是需要基于时间的通知,应该用本地通知,可以让设备的网络硬件休息一下。
2)远程推送有两个级别,一个是立即推送,另一个是针对功耗优化过的延时推送。如果不是真的需要即时推送,尽量使⽤延时推送。
总结
耗电量分析是应用开发中很难的课题,也是衡量性能的重要指标,做好电量优化,可以大幅度提升用户体验,在实际开发过程中,电量消耗往往是一个综合的结果,⼩到日常的代码习惯,积少成多,大到网络的乱用、不合理的网络超时、不合理的定位使用、不合理的CPU使用,都会带来能耗的过多消耗,而这些问题不仅仅会影响电量,还会影响用户体验。我们需要提高日常开发的代码质量,了解不同实现方式的差异点,优化页面卡顿,优化网络使用,优化GPS使用等等,只有综合这些因素,才能获得较好的用户体验。
在做耗电量分析的时候,⾸先要清楚耗电量较大的点,比如:网络、定位、CPU,从这些点入手分析,再详细分析每个点,细分每个点中的一些细节的影响,比如:网络中可能会存在导致耗电量过高的因素,我们可以使用哪些优化方法,同时根据我们的需求特点,怎么来优化,最终找到可优化点的,找到解决方案。在优化点寻找的过程中,我们⾸先可以使用Energy Impact来实时分析,各个维度指标是否有问题,占比是否合理,然后再通过Time Profiler、NetWork Profiler、Location Profiler等工具对各项指标进行详细分析,寻找优化点。其次我们可以使用Energy Log来横向对比各个维度的数据,来分析各个维度对总功耗的影响,比如:wifi数据传输和4G数据传输时,耗电量的对比,打开蓝牙和未打开蓝牙,能耗数据的对比,查看各个维度对能耗消耗影响的权重。然后我们可以使用Sysdiagnose可以进行不同场景、竞品app的对比分析,查找app的可优化点,也可以进行各种能耗数据的对比分析,以及优化前后的能耗数据对比,获取最终的优化效果。Sysdiagnose中的数量比较精确,同时数据比较全面,可以挖掘更多的信息,来辅助我们进行电量优化。