前言
功耗分析是移动应用开发中一个非常重要的课题,也是衡量应用性能表现的一个重要指标。但是在 iOS 设备上,由于苹果严格的限制,我们一直较难开展功耗分析的工作。
在 iOS 10 以前,我们还可以通过 IOKit 中的 IOPMPowerSource 私有接口,获取较为详细的电量信息,如电量、电压、电池温度等一系列的信息,腾讯的 GT 就是通过该接口获取电池的信息。然而,在 iOS 10 以及更高的系统中,该接口也被封印了,现在读取该接口,只能获取到很鸡肋的信息,如下图所示。
因此,iOS 平台上急切地需要一个功耗分析的工具。
Power Log(Sysdiagnose)
我们都知道,iOS 系统本身是有对电量的使用情况进行记录和分析的,所以我们才能在系统设置里看到过去一段时间里,各个 App 的前台工作时间和耗电情况。在进行了一整天的调研后,我震惊地发现,iOS 的耗电记录是可以导出的,并且它记录的详细程度简直令人发指!简单地说,它包括了过去几天里,系统整体的详细功耗情况、各个 App 在各个硬件上的耗电情况(包括第三方 App),等等一系列详细的数据。
有的同学可能遇到过,在向苹果反馈 Bug 时,有时苹果的工程师会要求你附上设备的诊断日志,其中,在遇到电池续航相关的问题时,苹果的工程师会让你提供一下电池的诊断日志。在电池的诊断日志中,就包含了电池电量的使用记录。
这些诊断工具在之前被苹果称为 Sysdiagnose,现在,它们被苹果统一归类到 Bug Reporting 的主题中,电池续航相关的诊断日志被称为“Power Log”。
我在苹果的 Bug Reporting 中发现了一份电池诊断日志的导出指南,其中仅仅简短地介绍了导出日志的几个步骤。我按照其中的步骤成功导出了电池续航日志,发现该日志其实是一个数据库,其中储存了几十张表。至于这几十张表中存储的内容是什么,各个字段的含义是什么,以及如何分析其中的数据,苹果的指南中则只字未提。好在经过一番查找后,我发现了腾讯的一篇博客 中有提到其中几张表的内容,有了这个开头后,我便顺腾摸瓜,大致了解了其中的结构。
下面,我简单地介绍一下,如何通过这个方法获取最全面的功耗信息,以及如何分析其中的数据。
获取数据
苹果在电池诊断日志的导出指南中详细说明了导出日志的步骤。我这里简要说明一下大概的步骤。
- 首先在你的测试机上,安装电量分析的 profile,安装完成后,iOS 才会记录最详细的功耗数据,并开放读取;(推荐下载后用 Airdrop 发送到手机上安装)
- 第二步,连接上 iTunes 并同步,这时 iTunes 就会自动把手机上的功耗的历史记录拷贝到电脑上;
- 第三步,断开设备,运行你的 App,这时设备已经在记录功耗信息,记得留意你运行 App 时的时间,因为稍后要和数据库中的时间戳进行匹配;
- 第四部,再次连接上 iTunes 并同步,这时 iTunes 就会自动把手机上的详细功耗记录拷贝到电脑上;
诊断日志的目录
到 iTunes 的同步文件夹(~/Library/Logs/CrashReporter/MobileDevice/你的手机名/
)下,找到以Powerlog_
开头,后缀是.PLSQL
或者.PLSQL.gz
的几个文件,这些就是记录了所有功耗信息的数据库文件了,可以使用简单的数据库查看工具打开看看。
分析数据
打开数据库后,我们可以看到里面有数百张表。苹果没有解释这些表的具体作用,只介绍了如何导出,因为苹果实际上只打算用这份记录来诊断问题,目前并没有直接向开发者开放。但我们可以通过各个表中的字段名,来了解各个表的大概用途。此外,腾讯的文档中介绍了其中比较重要的七张表,这节省了我们不少时间。下面列举一下关键的几张表的作用。
表名 | 内容 |
---|---|
PLBatteryAgent_EventBackward_Battery | 整机的电量信息,包含电流、电压、温度等信息。(每20秒记录一条数据) |
PLBatteryAgent_EventBackward_Battery_UI | 剩余电量百分比。(每20秒记录一条数据) |
PLIOReportAgent_EventBackward_EnergyModel | 整机不同硬件上的详细功耗数据。分别记录了 CPU、GPU、DRAM 等硬件的耗电量。 |
PLAccountingOperator_Aggregate_RootNodeEnergy | 各个 App 的详细耗电数据。记录各个 App 在各个硬件上的耗电量。(每小时更新一次数据) |
PLAccountingOperator_EventNone_Nodes | 各个硬件对应的 Node ID,以及各个 App 的对应的 Node ID。 |
PLAccountingOperator_EventNone_AllApps | 手机中安装的所有 App 的信息 |
PLApplicationAgent_EventForward_Application | App 运行状态记录。记录各个 App 在某个时间段以什么状态运行。 |
PLAppTimeService_Aggregate_AppRunTime | App 的运行时长统计。(每小时更新一次数据。 |
PLBatteryAgent_EventForward_LightningConnectorStatus | Lighting 接口连接状态 |
PLBatteryAgent_EventNone_BatteryConfig | 电池的配置信息。包括电池容量、循环计数、电池寿命、电池温度等信息。 |
PLBatteryAgent_EventNone_BatteryShutdown | 电池导致的意外关机记录。 |
PLButtonAgent_EventPoint_Button | 疑似物理按键的点击记录。 |
PLCameraAgent_EventForward_Camera | 相机使用记录。记录了相机类型和使用相机的 App |
PLConfigAgent_EventNone_Config | 本机的一些配置信息和一些系统设置。 |
PLDisplayAgent_Aggregate_UserTouch | 屏幕点击计数。每 15 分钟记录一条数据。 |
PLDisplayAgent_EventForward_Display | 屏幕亮度信息。包括流明、尼特、亮度滑竿值等信息。 |
PLProcessNetworkAgent_EventPoint_Connection | 网络连接记录。记录了发起网络连接的 App、地址、端口等信息。 |
PLXPCAgent_EventPoint_CacheDelete | 清除缓存的记录。包括申请的空间大小、清除缓存的耗时、清除的缓存大小、服务名称、紧急程度等信息。 |
我们结合几张表就可以简单地分析出一些衡量耗电量的维度,例如:
1、绘制电量百分比变化曲线
直接读取 PLBatteryAgent_EventBackward_Battery_UI
表中的数据即可。
2、iPhone 整体耗电量和温度变化
直接读取 PLBatteryAgent_EventBackward_Battery
表中的电量、温度数据,数据的记录间隔是 20 秒,基本上满足了各种各样的需求。
3、分析特定 App 的详细功耗数据
结合 PLAccountingOperator_Aggregate_RootNodeEnergy
和 PLAccountingOperator_EventNone_Nodes
两张表,可以得到某个 Bundle ID 对应的 App 在各个硬件上的耗电情况。
由于 PLAccountingOperator_Aggregate_RootNodeEnergy
中的每条数据,是记录该时间点之前一个小时内的耗电情况,所以我们可以知道在每个小时内,这个 App 在各个硬件上的耗电情况。例如,我们可以查到美拍在过去一个小时内的耗电情况,如下图所示,从中我们可以找出耗电较多的硬件,其中,耗电最多的是 RootNodeID 为 10 的硬件,也就是屏幕。
总结
Power Log 能够为我们提供十分详细和准确的功耗数据,从细节到整体都能够兼顾到。并且根据苹果官方的说法,记录详细的功耗数据并不会导致 iPhone 性能的下降,只是会占据一定的磁盘空间。不过,也因为它的数据量太大,导致它对我们不太友好。我们需要用 SQL 去读取、处理庞杂的原始数据,才能得到理想的信息。最好的方案是为此开发一个读取和分析的前端,这样才能够提高效率。此外,由于它的数据是离线获取的,这在某些情况下可能不是很方便。
但总的来说,Power Log 是十分强大的,它记录的信息之丰富让人印象深刻,也为我们的功耗分析提供了更好更强大的手段。