往期推文全新看点(文中附带全新鸿蒙5.0全栈学习笔录)
✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
✏️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
✏️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
✏️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
✏️ 记录一场鸿蒙开发岗位面试经历~
✏️ 持续更新中……
概述
应用功耗体验是指用户在使用应用时对应用所消耗电量(即功耗)的感受和反馈。高功耗不仅会导致设备发热、续航时间缩短,还可能引发用户的电量焦虑,从而影响用户体验、降低用户的使用意愿。综合业界的共识与实际用户的体验而言,应用功耗关键指标通常包括显示耗电量、CPU耗电量、GPU耗电量以及最终的总耗电量等。本文主要围绕功耗体验指标的CPU耗电量进行检测与分析,帮助开发者降低应用运行时的总耗电量。
应用功耗检测
应用功耗检测是指对移动应用在运行过程中的能量消耗进行测试和评估的过程。通过功耗检测,开发者可以了解应用的能耗情况,并进行优化,减少能源损耗、提高设备续航、提升用户体验。
应用功耗检测有以下几种方案:
- 基于设备实时帧率检测。
- 基于Profiler工具检测。
- 基于HismartPerf工具检测。
- 基于电源设备检测。
详细的检测方法如下:
基于设备实时帧率检测
- 打开帧率显示开关。
启用开发者选项:在设备上查看设置 > 系统中的开发者选项是否存在,如果不存在,可在设置 > 设备名称 中,连续七次单击“版本号”,直到提示“开启开发者选项”,点击确认开启后输入PIN码(如果已设置PIN),设备将自动重启,等待设备完成重启即可。
打开开发者模式中的"显示刷新频率"开关。具体操作:设置中搜索"开发者" -> “显示刷新频率”。
开关开启后共显示如图所示两个数字:
- 左侧数字代表当前所处的帧率档位。
- 右侧数字代表实际Render Service(下文简称RS)绘制帧率。具体指的是从应用触发到绘制再到最后的硬件送显整个过程中的实时帧率。有些时候虽然观察不到页面刷新,但实际RS一直在执行,这种情况也会导致耗电增加,例如重复的视图虽然会被视为无效,不会送显,但是RS仍会进行绘制。
通过帧率开关,可以对当前场景是否可能存在动画空跑问题有一个基础的概念,若当前页面实际静置或仅有一个低帧率动画刷新,那么右侧刷新帧率高于预期时,可以视作当前场景存在空跑问题。
- 查看重绘刷新区域。
打开开发者模式中的"显示重绘刷新区域"(俗称“脏区”)开关。具体操作:设置中搜索"开发者" -> “显示重绘刷新区域”。开关开启后,红色或蓝色的框线将会在屏幕上标注出当前屏幕正在刷新的位置与面积,同时框线的左上角有四位数字,表明当前脏区所处的坐标。脏区大小直接决定了每帧的绘制负载,开发者可以通过当前页面的脏区大小和变化情况,判断当前页面是否存在空跑问题。
说明
一般情况下帧率开关与脏区开关需要交替分析来定位脏区。不建议同时开启帧率开关与脏区开关,脏区的变化也会视作屏幕的刷新,帧率的数字变化也是脏区的一部分,两者同时开启可能会互相影响,导致显示的帧率高于实际页面帧率。
基于Profiler工具检测
设置开发者选项:
- 打开开发者选项,打开USB调试并关闭USB充电。关闭USB充电主要是为了避免充电造成的功耗差异。
启用开发者选项:在设备上查看设置 > 系统中的开发者选项是否存在,如果不存在,可在设置 > 设备名称 中,连续七次单击“版本号”,直到提示“开启开发者选项”,点击确认开启后输入PIN码(如果已设置PIN),设备将自动重启,等待设备完成重启即可。
Profiler工具查看功耗:
DevEco Profiler是DevEco Studio内置集成的场景化的性能分析工具。它提供了实时监控 (Realtime Monitor)能力,可以全方位的进行设备资源监测,可以帮助开发者识别功耗故障。通过性能工具,开发者可以及时了解应用或元服务的CPU、内存、图形等资源的使用情况,高效定界问题所在,快速定位问题代码,提高解决问题的效率。
使用Profiler工具查看功耗的步骤如下:
- 在设备上启动需要检测的应用。
- 打开Profiler工具,在左上角选择设备、应用以及进程。
图1 Profiler应用选择示意图
- 查看实时功耗。
使用Profiler实时监控能力观察设备温度变化,以及各器件的功耗数据,确定发热场景和功耗来源。
图2Profiler实时监控示意图
- Temperature:检测应用运行时的设备温度,3s为一个采集周期,功耗过高时会导致温度上升、设备发热。
- Device Current:当前设备最大电流、平均电流以及最新的电流值(如果出现负数,说明是在充电)。
- Energy:展示各项部件(主要关注CPU、Display、GPU)的周期内平均功耗占比,采集周期也是3s。
说明
- 上图区域展示时间窗内CPU、Memory、FPS、GPU、Energy资源的实时使用情况,将鼠标悬浮于统计图中任意位置,打开时间标线,左右移动鼠标并结合时间轴可查看不同时间点上的实时信息。
- 端侧的采集数据可能会略有偏差,开发者也可以直接录制Frame分析任务,直接查看Energy泳道,了解更加详细准确的功耗相关数据。详情如下图:
基于HismartPerf工具检测
通过HiSmartPerf-Device工具可以在手机设备上简单、快捷地采集FPS、功耗、温度、负载等基础性能数据,并生成测试报告,可以帮助开发者快速了解应用的性能情况。
-
获取工具
点击下载Device版本工具并进行安装。 -
采集性能数据
在手机端点击桌面SmartPerf应用图标打开HiSmartPerf-Device工具,设置好采集要求之后,即可开始进行性能数据采集。
基于电源设备检测
指通过使用第三方精密仪器(如程控电源等)来测试设备的整体耗电量。这种方法可以获取比较准确的电量数据,但测试成本较高,且无法直接针对单个应用进行功耗评估。
问题分析流程
图3定位流程图
在进行功耗相关问题定位时,首先需要关闭USB充电模式,使用Profiler实时监控观察温度以及功耗变化,明确问题的具体场景以及功耗来源;然后开启Frame录制,通过Trace进行CPU频点与负载分析。此时可能会遇到以下三种情况:
- GC线程负载高。
需要通过Allocation和Snapshot模板来分析内存使用情况。
- UI线程负载高。
需要通过Trace泳道分析是否存在冗余绘制及组件未复用等情况,主要是结合应用主进程、render_service、RSUniRenderThre以及RSHardwareThrea这些管线里面的帧率、帧长、未送显情况进行详细分析。
- 应用侧其他线程负载高。
需要借助Callstack泳道分析函数栈,排查应用的业务逻辑是否存在异常,是否频繁执行了长耗时任务,或者进入异常业务逻辑导致了无限循环。
针对以上情况进行详细的分析定位,确认根因后进行修复,然后观察功耗以及发热情况是否满足性能要求,如果不能满足,则重复进行分析定位。
Trace分析CPU负载
案例一:应用侧某线程负载过高
问题背景: 某应用使用过程中,边刷视频边查看评论或推荐时,手机发烫严重,关闭应用后逐渐恢复正常。
分析详情:
- 在Profiler工具中开启Frame分析任务并复现问题场景。
- 观察CPU Core泳道找到运行时长占比比较高的线程
选择CPU Core泳道,通过下方详情区可以看出,应用进程占比时长较高。
查看CPU频点情况,通过查看Frequency泳道发现CPU核的频点都很高,CPU调度非常频繁。
Frequency子泳道:表示CPU频率,鼠标悬浮在Frequency泳道上,可以看到CPU的运行频率。
当所有CPU核频点都较高时,选择CPU Core泳道,查看CPU负载来源。通过详情区,可以看到CPU负载主要来源于应用侧的子线程(线程号55523)。
-
根据CPU高负载线程类型进行详细排查。
本案例中,CPU负载主要来源于应用侧的子线程(线程号55523)。需要借助Callstack泳道分析该线程执行的任务,结合函数栈排查业务逻辑是否存在异常。大多情况下都是由于该线程频繁执行长耗时任务或者无限循环逻辑导致的。
案例二:GC线程负载过高
问题背景: 某应用使用期间,屏幕发烫严重,壳温高达40摄氏度;结束应用后,温度自行恢复正常。
分析详情:
- 在Profiler工具中开启Frame分析任务并复现问题场景。
- 观察CPU Core泳道找到运行时长占比比较高的线程。
选择CPU Core泳道,通过下方详情区可以看出,应用进程占比时长较高。不同应用的应用进程名称不同,一般与应用包名一致。
查看CPU频点情况,通过查看Frequency泳道的CPU频率可以看出CPU部分核上频点很高,基本保持在最高频状态运行。即下图中的CPU10、CPU11,其对应的Frequency子泳道基本被填满。
当部分核频点较高时,选择CPU频点比较高的核对应的Slice子泳道,查看CPU负载来源。即CPU10与CPU11对应的Slice子泳道,通过详情区可以看到CPU负载主要来源于应用进程的OS_GC_Thread线程。
- 根据CPU高负载线程类型进行详细排查。
本案例中,CPU负载主要来源于应用进程的OS_GC_Thread线程。针对GC线程负载高的情况,需要借助Allocation和Snapshot模板具体分析内存使用情况。
案例三:UI主线程负载过高
问题背景: 在某应用上进入直播页面进行观看,功耗超100mA,手机温度持续升高。
分析详情:
- 在Profiler工具中开启Frame分析任务并复现问题场景。
- 观察CPU Core泳道找到运行时长占比比较高的线程。
选择CPU Core泳道,通过下方详情区可以看出,应用进程占比时长较高。
查看CPU频点情况,通过查看Frequency泳道发现CPU部分核(CPU10、CPU11)的频点很高,且每个CPU核调度都非常频繁。
选择CPU Core泳道,查看CPU负载来源。通过详情区,可以看到CPU负载主要来源于应用UI主线程(线程号43436,与应用进程号一致为主线程)。
- 根据CPU高负载线程类型进行详细排查。
本案例中,CPU负载主要来源于应用UI主线程。需要分析UI主线程的Trace泳道判断是否存在冗余绘制及组件未复用等情况。
找到UI主线程对应的Trace泳道(可以根据应用包名或上一步中的线程号查找)。选择对应的线程泳道,可以看到详情区包含了线程运行状态,选择Thread States,可以看出Running状态占比非常高。
查看Slice List,检查是否存在冗余绘制及组件未复用等情况。选择Slice List,发现id为-1的Image一直在执行绘制任务,Occurrences达到了4万多次。然后借助ArkUI Inspector工具进行排查确认组件是否存在冗余绘制情况。
常见根因与解决方案
LTPO低功耗
LTPO指自适应刷新率技术。通过按需自适应调整显示刷新率,实现最优的性能和功耗体验。应用通过适配LTPO可以精细化场景帧率控制,降低场景负载,减少偶发卡顿,降低场景功耗。
省电和深色模式
- 省电模式:一种通过调整设备的设置来降低系统功耗的功能,例如适当降低屏幕亮度和CPU性能。
- 深色模式:深色模式是应用程序的一种背景颜色设置,用于将应用程序显示背景颜色改为深色调,例如黑色或深灰色。深色模式使用了更少的像素点和背光,因此能够减少能量的消耗。