4

iOS性能优化之耗电检测

 2 years ago
source link: https://www.diffit.cn/2020/09/03/EnergyDetection/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
  • 如果某个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查看电量情况,如图
    EnergyDetection-01.png
  • 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进行过滤
    EnergyDetection-02.png
    • 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(需要登录开发者账号)
      Energy-02.png
    • 下载完成后通过隔空投送发到测试手机上安装。
    • 不要重启手机,等待10到30分钟,手机连上电脑,通过 iTunes 同步到电脑上。
  • 日志位置
    • iOS: 设置 > 隐私 > 分析 > 分析数据 > (定位sysdiagnose文件,使用隔空投送发送到macOS上面).
    • macOS: ~/Library/Logs/CrashReporter/MobileDevice/[Your_Device_Name]/
    • Windows 10:
      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 SQLiteNavicat 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。
    Energy-03.png
  • 得到每个App的唯一标识后,我们就可以去PLAccountingOperator_Aggregate_RootNodeEnergy表里看电量消耗数据了:
    SELECT *,DATETIME(timestamp,'unixepoch','localtime') from PLAccountingOperator_Aggregate_RootNodeEnergy WHERE NodeID=10521 ORDER BY timestamp DESC;
    Energy-04.png
  • 表中的Energy就是对应消耗的电量了,这里的单位在iOS9是mAh,iOS9及以上应该是 1/1000 mAh。比方测试2020-01-08 17:00:00这个时间耗电量,可以执行SQL语句计算出来。这个耗电量为3182 / 1000 = 3.182 mAh
    SELECT SUM(Energy) from PLAccountingOperator_Aggregate_RootNodeEnergy WHERE NodeID=10521 AND timestamp=1578474000 ORDER BY timestamp DESC;
    Energy-05.png
  • 如果想知道运行这个App这段时间内的温度,可以PLBatteryAgent_EventBackward_Battery 表中获取,但是因为该表的数据是整个机器的,所以我们需要根据对应的时间节点来观察数据:
    Energy-06.png

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK