鸿蒙开发功耗检测(一)

应用耗电异常,很多时候是 CPU 高负载在背后作祟。本文基于官方文档,把功耗检测的定位、实现原理、事件场景、限制梳理清楚。
一、功耗检测
功耗检测主要提供 CPU 高负载检测,可以通过订阅相关事件实现检测。
目前仅提供 ArkTS 接口支持。
HiAppEvent 提供订阅 CPU 高负载事件,下篇文档中介绍如何使用。
二、实现原理
系统会周期性及在特定条件(如前后台切换)下,采集三方应用在 CPU 上的运行时间,并每 5 分钟统计一次前 5 分钟的平均负载。
触发机制:若负载超过设定门限,将触发 HiAppEvent 预警事件。
负载计算方式
负载是根据 CPU 核数归一化后的运行时间。
计算示例:
在 5 分钟内,应用进程在 10 核 CPU 上运行了 5 分钟,其平均负载为:
5(CPU 上运行时间)/ 5(统计周期分钟)/ 10(核数)= 10%
三、CPU高负载事件的场景
基础场景(3 种)
| 场景 | 触发条件 |
|---|---|
| 1. 应用在前台时触发 CPU 高负载事件 | 5 分钟内平均负载 大于 30% |
| 2. 应用在后台时触发 CPU 高负载事件 | 5 分钟内平均负载 大于 10% |
| 3. 应用线程高负载异常事件 | 单线程 1 分钟内平均负载 大于 70% |
后台高负载的 3 档规格
CPU 后台高负载场景还支持以下 3 档规格:
| 档位 | 触发条件 |
|---|---|
| 1 | 应用在后台时触发 CPU 高负载事件:10 分钟内平均负载大于 7% |
| 2 | 应用在后台时触发 CPU 高负载事件:30 分钟内平均负载大于 2% |
| 3 | 应用在后台时触发 CPU 高负载事件:60 分钟内平均负载大于 1% |
这 3 档规格与基础场景的"后台 5 分钟 > 10%"是并列关系,可根据需要选择不同的检测粒度。
四、限制
| 场景 | 默认抓取限制 |
|---|---|
| 前台 CPU 高负载异常 | 单应用默认一天只抓取 1 次调用栈,1 次采样栈 |
| 后台 CPU 高负载异常 | 单应用默认一天只抓取 1 次调用栈,1 次采样栈 |
| 线程 CPU 高负载异常 | 单应用默认一天只抓取 1 次采样栈 |
备注:相关配置可自定义
五、日志规格
在订阅事件开发步骤的最后一步中,获取到系统事件数据的处理日志后,可通过查找日志中 external_log 记录的故障日志文件路径,得到故障日志。
事件数据示例
HiAppEvent eventInfo={
"domain":"OS",
"name":"CPU_USAGE_HIGH",
"eventType":1,
"params":[
"begin_time":1765959898079,
"bundle_name":"com.xpower.test",
"bundle_version":"1.0.0",
"end_time":1765959958079,
"external_log":[
"/data/storage/el2/log/hiappevent/CPU_USAGE_HIGH_1765959959260_0.log"
],
"fault_type":3,
"foreground":true,
"log_over_limit":false,
"threads":[
{
"name":"WorkerThread",
"tid":29164,
"usage":72
}
],
"time":1765959959257,
"usage":72
]
}
字段说明
| 字段 | 说明 |
|---|---|
external_log | 记录故障日志的路径,在路径下可获取到故障日志 |
foreground | 是否前台(示例中为 true) |
fault_type | 故障类型(示例中为 3) |
threads | 线程信息,包含线程名 name、线程 ID tid、使用率 usage |
usage | 负载使用率(示例中为 72) |
两类故障日志
| 日志类型 | 说明 |
|---|---|
| 调用栈故障日志 | 触发故障时当前故障线程的调用链堆栈信息。 |
| 采样栈故障日志 | 主动采集的 perf 日志。 |
说明:
-
功耗检测 = CPU 高负载检测:当前聚焦在 CPU 高负载这一项,通过 HiAppEvent 订阅事件实现,仅支持 ArkTS 接口。
-
负载是"归一化"后的值:不是简单的 CPU 占用百分比,而是 运行时间 / 统计周期 / 核数,这个计算方式要理解清楚,否则容易误判。
-
前台和后台门限差异大:
-
前台:5 分钟平均负载 > 30% 才触发
-
后台:5 分钟平均负载 > 10% 就触发
-
后台要求更严格,因为后台高负载对用户体验和续航影响更大。
-
-
线程高负载是单线程维度:1 分钟内平均负载 > 70% 触发,和前两种是不同维度的检测。
-
后台还有三档长周期规格:
-
10 分钟 > 7%
-
30 分钟 > 2%
-
60 分钟 > 1%
-
周期越长门限越低,适合检测"慢性"高负载问题。
-
-
抓取次数有默认限制:单应用一天只抓 1 次调用栈 + 1 次采样栈(线程高负载只有 1 次采样栈),避免频繁抓取影响性能。需要更多数据要自定义配置。
-
日志通过
external_log路径获取:事件数据里的external_log字段记录了故障日志的文件路径,拿到路径后去读文件即可。 -
两类故障日志用途不同:
-
调用栈故障日志:看故障线程的调用链,定位代码位置
-
采样栈故障日志:perf 日志,看 CPU 采样分布
-
前者定位"哪行代码",后者定位"时间花在哪"。
-
-
1 天 1 次限制要注意:如果当天已经抓过一次,再触发高负载可能拿不到新日志,调试时要留意。需要更多数据,按《自定义参数》调整。
如果应用被用户反馈耗电快,可以先用这套检测跑一段时间,看看是否触发 CPU 高负载事件,拿到日志后再针对性优化。特别是后台高负载,门限只有 10%,是耗电问题的高发区。
更多推荐
所有评论(0)