基于 iOS Sysdiagnose 的耗电自动化测试

基于 iOS Sysdiagnose 的耗电自动化测试

目录


一、基本概念

1.1 电量单位

  • 电量(Q):用 Q 表示,单位是库仑(C)
  • 电流(I):用 I 表示,单位是安培(A)
  • 时间(t):用 t 表示,单位是秒(s)
  • 关系式:Q = I × t
  • 单位换算:1A = 1000mA

1.2 电池容量

  • mAh(毫安时):手机电池容量常用单位
  • 含义:1000mAh 的电池容量,表示在电流 1000mA 的情况下,可以持续放电 1 小时
  • mAh 和库仑的关系
    1mAh = 3.6 库仑
    1000mAh = 1000mA × 1h = 1000mA × 3600s = 1A × 3600s = 3600 库仑

1.3 能耗单位

  • mWh(毫瓦时):能耗单位
  • mWh 和 mAh 的关系
    mWh = mAh × U(电压)
  • 能量计算公式
    能量 E = 功率 P × 时间 t
    功率 P = 电压 U × 电流 I
    因此:mWh = U × I × t = U × mAh

二、测试结果

2.1 测试前置条件

  • 手机型号:iPhone 6S
  • 出厂电池容量:1715mAh
  • 测试应用:腾讯会议
  • Bundle IDcom.tencent.meeting.db.haven
  • 测试时间:1 小时(独占模式)
  • 测试时间段:2021-1-13 16:00 ~ 17:00

2.2 1 小时测试结果

2.2.1 整机耗电量

  • 统计时长:3604s
  • 整机耗电量:574mAh(精准值)

2.2.2 基于能耗计算的耗电量

  • 平均电压:3.885V
  • 模块总能耗:2175679mWh
  • 计算得到总耗电量:mAh = 2175679 / 3885 = 560mAh

2.2.3 应用耗电量

  • 平均电压:3.885V
  • 腾讯会议各模块总能耗:2050807mWh
  • 计算得到腾讯会议总耗电量:mAh = 2050807 / 3885 = 528mAh

2.2.4 数据差异说明

  • 560mAh 和 574mAh 的差距:主要是由于电压存在波动,而计算采用的是平均电压值
  • 应用耗电量小于模块总耗电量:在独占模式下,App 的总耗电量(528mAh)小于模块的总耗电量(560mAh),是由于系统存在其他后台进程

三、iOS Sysdiagnose 的使用方法

3.1 开启系统诊断

  1. 下载 Profile(有效期 7 天),并安装到 iOS 设备(可以使用 AirDrop 传递到电脑)
  2. 信任 Profile
  3. 打开 iPhone 系统设置 → 通用 → 描述文件
  4. 选择信任 System Debug Profile
  5. 同步设备信息到电脑:这个同步操作用于保存历史数据
  6. 开始测试
  7. 复现问题或开始测试
  8. 记录问题出现的日期或时间
  9. 再次同步信息到电脑:测试完成后再次同步

⚠️ 注意事项:重启手机会导致 Profile 文件失效

3.2 关闭系统诊断

  1. 打开 iPhone 系统设置 → 通用 → 描述文件
  2. 选择移除 System Debug Profile
  3. 重启手机

3.3 诊断日志存储位置

电池诊断日志文件名以 Powerlog_ 开头,并以 .PLSQL.PLSQL.gz 结尾。

macOS

~/Library/Logs/CrashReporter/MobileDevice/[Your_Device_Name]/

iOS

Settings.app > Privacy > Analytics > Analytics Data

Windows 10

%appdata%\..\Local\Packages\AppleInc.iTunes_devicename\LocalCache\Roaming\AppleComputer\Logs\CrashReporter\MobileDevice\[Your_Device_Name]/DiagnosticLogs/

3.4 同步设备信息(iPhone → Mac)

打开 Finder → 左侧找到对应的设备 → 点击右下角的同步按钮

同步设备信息


四、电池诊断日志分析

电池诊断日志使用数据库进行存储,数据库包含多张表,表数量与 iOS 系统版本相关。例如,iOS 14 系统有 450 张表。

4.1 整机电量表

表名PLBatteryAgent_EventBackward_Battery

以 20s 的采样频率记录本机的电量、温度、电压、电流等信息,少数样本不受 20s 采样频率限制。

4.1.1 查询示例

SELECT
    datetime(timestamp, 'unixepoch', 'localtime') AS time,
    Level,
    RawLevel,
    AbsoluteLevel,
    MaxCapacity,
    AbsoluteCapacity,
    DesignCapacity,
    AppleRawMaxCapacity,
    AppleRawCurrentCapacity
FROM PLBatteryAgent_EventBackward_Battery
WHERE timestamp > 1610503788.63826

整机电量查询结果

4.1.2 字段解释

重要字段

  • DesignCapacity:电池出厂容量
  • iPhone 6S 容量是 1715mAh,查询结果 1690mAh,基本一致
  • AbsoluteCapacity:电池当前容量

其他字段

  • Level:手机显示的电量剩余百分比
  • RawLevel:剩余时间电量百分比
  • MaxCapacity:电池最大容量百分比,固定值 100
  • CurrentCapacity:同 Level,看起来是整型
  • Voltage:电池当前电压值,存在小幅度的波动

计算字段

  • 已消耗电量 = AppleRawMaxCapacity – AppleRawCurrentCapacity
  • 电池的实际容量 = AppleRawMaxCapacity – AppleRawCurrentCapacity + AbsoluteCapacity

示例:电池的实际容量计算出来固定为 1380mAh,也就是说 iPhone 6S 的出厂电量为 1690mAh,电池衰退之后目前为 1380mAh

电池容量计算

4.1.3 一小时整机的电量消耗

查询结果:3604.26s 时间内,手机耗电量 574mAh

SELECT
    t1.start_ts,
    t1.start_cap,
    t1.start_time,
    t2.end_cap,
    t2.end_ts,
    t2.end_time,
    (t2.end_ts - t1.start_ts) AS delta_ts,
    (t1.start_cap - t2.end_cap) AS delta_cap
FROM
    (
        SELECT
            datetime(timestamp, 'unixepoch', 'localtime') AS start_time,
            timestamp AS start_ts,
            AbsoluteCapacity AS start_cap
        FROM PLBatteryAgent_EventBackward_Battery
        WHERE timestamp >= 1610524800 AND IsCharging = 0
        ORDER BY start_time
        LIMIT 1
    ) t1,
    (
        SELECT
            datetime(timestamp, 'unixepoch', 'localtime') AS end_time,
            timestamp AS end_ts,
            AbsoluteCapacity AS end_cap
        FROM PLBatteryAgent_EventBackward_Battery
        WHERE timestamp >= 1610524800 + 3600 AND IsCharging = 0
        ORDER BY end_time
        LIMIT 1
    ) t2

一小时整机耗电量查询结果

4.2 节点关系表

表名PLAccountingOperator_EventNone_Nodes

硬件模块和 APP 在其他表的信息统计统一使用的 NodeId,通过这个表可以知道具体 NodeId 对应的硬件模块或者 APP。

4.2.1 查询示例

SELECT * FROM PLAccountingOperator_EventNone_Nodes;

节点关系表查询结果

4.2.2 字段解释

  • IsPermanent:Node ID 是否固定不变
  • 硬件模块的 Node ID 是固定不变的
  • APP 的 Node ID 可能发生变化(比如 APP 卸载重装)

4.3 节点耗电详情表

表名PLAccountingOperator_Aggregate_RootNodeEnergy

耗电详情表按小时统计数据,统计数据写入数据库表有一个小时的延迟。

示例:统计 9~10 点的耗电详情,可能要等到 11 点才能拿到完整的统计数据

4.3.1 字段解释

  • Energy:能耗,单位 mWh,mWh = mAh × 电压

4.3.2 一小时整机能耗详情

查询结果:总能耗为 2175679.927882,16:00~17:00 平均电压为 3.885V

mAh = 2175679 / 3885 = 560mAh

这个数值和 2.2.1 例子中的 574mAh 基本一致。

查询总能耗

-- 查询总能耗
SELECT
    datetime(timestamp, 'unixepoch', 'localtime') AS time,
    timestamp,
    sum(Energy) AS total_energy
FROM PLAccountingOperator_Aggregate_RootNodeEnergy
WHERE timestamp = 1610525013.0
ORDER BY time

查询各个模块的能耗

-- 查询各个模块的能耗
SELECT
    datetime(timestamp, 'unixepoch', 'localtime') AS time,
    timestamp,
    sum(Energy) AS total_energy,
    RootNodeID,
    (SELECT Name FROM PLAccountingOperator_EventNone_Nodes WHERE ID = PLAccountingOperator_Aggregate_RootNodeEnergy.RootNodeID) AS RootNodeName
FROM PLAccountingOperator_Aggregate_RootNodeEnergy
WHERE timestamp >= 1610525013.0
GROUP BY RootNodeID, timestamp
ORDER BY time

整机能耗详情

4.3.3 一小时应用能耗详情

查询结果:总能耗为 2050807,16:00~17:00 平均电压为 3.885V

mAh = 2050807 / 3885 = 528mAh

APP 总能耗

-- APP 总能耗
SELECT
    datetime(timestamp, 'unixepoch', 'localtime') AS time,
    timestamp,
    sum(Energy),
    NodeID,
    (SELECT Name FROM PLAccountingOperator_EventNone_Nodes WHERE ID = PLAccountingOperator_Aggregate_RootNodeEnergy.NodeID) AS NodeName
FROM PLAccountingOperator_Aggregate_RootNodeEnergy
WHERE NodeID = (SELECT ID FROM PLAccountingOperator_EventNone_Nodes WHERE Name = 'com.tencent.meeting.db.haven')
    AND timestamp = 1610525013.0
ORDER BY time

APP 各模块能耗

-- APP 各模块能耗
SELECT
    datetime(timestamp, 'unixepoch', 'localtime') AS time,
    timestamp,
    ID,
    timeInterval,
    Energy,
    NodeID,
    (SELECT Name FROM PLAccountingOperator_EventNone_Nodes WHERE ID = PLAccountingOperator_Aggregate_RootNodeEnergy.NodeID) AS NodeName,
    RootNodeID,
    (SELECT Name FROM PLAccountingOperator_EventNone_Nodes WHERE ID = PLAccountingOperator_Aggregate_RootNodeEnergy.RootNodeID) AS RootNodeName
FROM PLAccountingOperator_Aggregate_RootNodeEnergy
WHERE NodeID = (SELECT ID FROM PLAccountingOperator_EventNone_Nodes WHERE Name = 'com.tencent.meeting.db.haven')
    AND timestamp = 1610525013.0
ORDER BY time

应用能耗详情


五、电量自动化测试

电量自动化需要借助一个 USB 控制电路板,用于控制手机充断电。电源线无法直连 Mac 的原因是因为 USB 控制面板只有 Windows 版本。

连接示意图和流程如下:

电量自动化测试连接示意图


六、电量日志自动解析

6.1 目标

  1. 自动分析应用能耗和变化趋势
  2. 每次测试整机的能耗变化趋势
  3. 应用能耗的变化趋势

  4. 能耗变化自动输出

  5. 当应用能耗发生变化时,能够自动输出应用能耗分布详情
  6. 能够直观地看到变化的部分

6.2 分析视图

电量日志分析视图

6.2.1 系统电量百分比

观察手机电量的变化趋势,每次电量测试的时候,手机都是断电状态。

  • 断电:对应下行曲线
  • 充电:对应上行曲线

PLBatteryAgent_EventBackward_Battery 原始数据得到绘制曲线

6.2.2 系统每小时电量

系统电量百分比只能看到系统的电量变化趋势,并不能直观地看到系统每小时的耗电量,这也是系统每小时电量视图存在的原因。

它是由 PLBatteryAgent_EventBackward_Battery 原始表数据,计算每个整点的电量差值而得到绘制曲线

6.2.3 应用每小时能耗

存在实际能耗和每小时能耗两条曲线的原因:

  • 当应用的测试时间不足一个小时时,实际能耗要转换为每小时能耗,这样才方便能耗的对比
  • 建议:每次测试时间都是从整点开始跑满一个小时

6.2.4 应用每小时耗电量

应用每小时耗电量是根据应用的能耗和电压计算而来的,目的主要是为了方便得出应用的具体耗电量,这样也方便和整机的耗电量进行对比。

注意:由于电压取的是一个小时的平均值,所以应用每小时计算出的耗电量和实际的耗电量可能存在小量误差


七、常见问题

7.1 电量日志时间戳无法更新

问题:有些手机在获取电量日志的时候,可能存在电量日志时间戳无法更新的情况

解决方法:目前知道的解决方法是还原系统

7.2 为什么存在实际能耗和每小时能耗

主要是由于测试时间可能不足一个小时,统一换算成每小时能耗,方便对比。


八、电量分析方法对比

方法名 优点 缺点 方法改进
人眼计时法 简单,不需要辅助工具
  • 无法拿到精准的电量数据
  • 电量 100% 并不是 100%
  • 需要人工参与,效率低
  • 无法精准到具体的模块耗电
  • 电量从 100% 下降到 99% 开始记时测试
  • 电量 100%,仍然充电 20 分钟
Instruments 提供的能量日志方法
  • 数据展示直观
  • 分模块统计能耗等级和时长
  • 仍然无法拿到精准的电量数据 mAh
  • 模块划分比较粗糙
  • GPU、摄像头、视频编解码芯片的耗电量仍然不可知
苹果系统诊断方法 提供系统、应用、模块的电量详情
  • 非公开方式,无文档说明
  • 数据库包含多张数据表,iOS 12 有多达 406 张表
  • 电量是按小时统计,只能整点开始测试
挑选出几张核心的数据表

8.1 自动化改进

即使有苹果提供的系统电量诊断方法,进行电量测试依然需要人工介入,费时费力,主要表现在:

  • 每次测试前需要充电
  • 测试过程中需要断电
  • 只能整点开始测试
  • 测试结束之后需要等待 2、3 个小时之后才能拿到测试数据
  • 测试数据需要从 iPhone 手工同步到电脑上进行分析

一轮测试下来基本需要耗费几个小时

8.2 计算方法说明

通过能耗和电压去计算系统的整机耗电量,和应用的耗电量。


九、电量优化建议

9.1 平台优化建议

平台 优化建议
mac
  • Timer 优化
  • 冗余布局约束
  • 冗余控件刷新
  • 减少音频动画
  • 优先使用集成显卡
Windows
  • 减少音频动画
  • 优先使用集成显卡
  • 减少链路格式
Android
  • 减少音频动画
  • 视频显示方式由先放大后截取修改为缩小显示上下黑边
  • 开启硬编硬解
iOS 待补充

9.2 iOS 平台优化建议

注意:iOS 平台的优化建议需要根据实际测试结果和性能分析进行补充


参考资料

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Index