来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

功耗优化是应用体验优化的一个重要课题,高功耗会引发用户的电量焦虑,也会导致糟糕的发热体验,从而降低了用户的使用意愿。而功耗又是涉及整机的长时间多场景的综合性复杂指标,影响因素很多。不论是功耗的量化拆解,还是异常问题的监控,以及主动的功耗优化对于开发人员来说都是很有挑战性的。

本文结合抖音的功耗优化实践中产出了一些实验结论,优化思路,从功耗的基础知识,功耗组成,功耗分析,功耗优化等几个方面,对 Android 应用的功耗优化做一个总结沉淀。
GitHub

一丶功耗基础知识介绍

首先我们回顾一下功耗的概念,这里比较容易和能耗搞混。解释一下为什么手机上用mA(电流值) 来表征功耗水平,用 mAh(物理意义上是电荷值)来表征能耗水平。我们先来看几个物理公式。

P = I × U, E = P × T

能耗(E):即能量损耗,指计算机系统一段时间内总的能量消耗,单位是焦耳(J)

功耗(P):即功率损耗,指单位时间内的能量消耗,反映消耗能量的速率,单位是瓦特(W)

电流(I):指手机电池放电的电流值,手机常用 mA 为单位

电压(U):指手机电池放电的电压值,标准放电电压 3.7V,充电截止电压 4.35V,放电截止电压 2.75V (以典型值举例,不同设备的电池电压数值有差异)

电池容量 :常用单位 mAh,从单位意义上看是电荷数,实际表征的是电池以典型电压放电的时长。

如下面的功耗测试图所示,手机通常以恒定的典型电压工作,为了计算方便,就把电压恒定为 3.7V,那么 P = I × 3.7, E = I × 3.7 × T,即用 mA 表征功耗,mAh 表征能耗。

总结:对同一机型,我们用电池容量(mAh)变化的来表征一段时间总能耗,用平均电流(mA)来表征功耗水平;如 4000mAh 电池的手机刷抖音 1 小时耗电 11%,耗电量(能耗)440mAh,平均电流 440mA

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

这里列举了手机硬件的基本形态,每个模块又是由复杂的器件构成。如我们常说的耗电大头 SoC 里就包含 CPU 的超大核,大核,小核,GPU,DDRC(内存接口),以及外设区的各种小 IP 核等。所以整机的功耗最终就可以拆解为各个器件的功耗,而应用的功耗就是计算其使用的器件产生的功耗。

以抖音的 Feed 流场景为例,亮度固定 120nit、7 格音量、WiFi 网络下,我们对抖音做了器件级的功耗拆解。可以看到抖音的 feed 功耗主要集中在 SOC(CPU,GPU,DDR),Display,Audio,WIFI 等四个模块。

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

5.1.2.电池电量计

PowerMonitor 虽然测量结果最准确。但是需要拆机比较麻烦。我们还可以通过谷歌 BatteryManager 提供的接口直接读取电池电量计的统计结果来获得电流值。

电池电量计负责估计电池容量。其基本功能为监测电压,充电/放电电流和电池温度,并估计电池荷电状态(SOC)及电池的完全充电容量(FCC)。有两种典型的电量计:电压型电量计和电流型电量计,目前手机上使用的电量计主要是电流型电量计。

  • 电压型电量计:简单讲就是检测当前电压,然后查询电压-电池容量对应表,获得电量估算
  • 电流型电量计:也叫库仑计,原理是在电池的充电/放电路径上的连接一个检测电阻。ADC 量测在检测电阻上的电压,转换成电池正在充电或放电的电流值。实时计数器(RTC)则提供把该电流值对时间作积分,从而得知流过多少库伦。

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

从实践结果上看,由于不同的手机使用的电量计不同,导致直接读取出来的电流值单位也不同,需要做数据转化。为了简化电池数据的获取,我们开发了 Thor SDK,只保留电流、电压、电量等指标的采集过程,针对不同机型做了数据归一处理,用户可以不用关心内部实现,只需要提供需要采样的数据类型、采样周期就可以定时返回所需要的功耗相关的数据,我们用 Thor 对比 PowerMonitor 进行了数据一致性的校验,误差

此外我们做了 Thor 采集功能本身的功耗影响,可以看到 1s 采集 1 次的情况下,平均电流上涨了 0.59mA,所以说这种方案的功耗影响非常低,适合线上采集电流值。

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

5.2. 功耗归因

从功耗评估我们可以判断应用的整体耗电情况,但具体到某个 case 高耗电的原因是什么,就要具体问题选择不同的工具来进行分析了。目前可以直接归因到业务代码的主要是 CPU 相关的工具,这也是我们目前分析问题的主要方向,后续我们也会建设流量归因等能力,下面我列举了常用的分析工具。

5.2.1.

谷歌官方提供的分析工具,需要先进行功耗测试,再通过 adb 抓取 bugreport.zip,再通过网页工具打开,可提供粗粒度的功耗归因。

本质上是对 systemserver 里的各种服务统计信息+手机状态+内核统计信息(kernel 唤醒)的展示,应用耗电的估算依赖厂商配置的 power_profile.xml。比较适合对整机耗电问题做耗电归因,如归因到某应用耗电较高。

对于单个应用,由于对 wakelock,alarm,gps,job,syncservice,后台服务运行时长等统计的比较详细,比较适合做后台耗电的归因。对于网络异常,CPU 异常,只能看到消耗较多,无法归因到具体业务。developer.android.com/topic/perfo…

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

5.2.2.

相比于 BatteryHistorian 需要先手动测试,再 adb 抓取的操作繁琐,AS 自带的 Profiler 提供了 Energy 的可视化展示。使用 debug 版本的应用,可以直观的看到功耗的消耗情况,方便了线下测试。需要注意的是这里展示的功耗值是通过 GPS+网络+CPU 计算的拟合值,并不是真实功耗值,只表征功耗水平。

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

6.1.DISPLAY

显示功耗的优化主要围绕对屏幕,GPU,CPU,视频解码器,TP 等器件降级使用或者减少处理,尽量使用硬件处理等实现的。对于屏幕而言主要是降低亮度,刷新率,TP 扫描频率等。

6.1.1.屏幕亮度

屏幕亮度是屏幕功耗的最大来源,亮度和功耗几乎是正比的关系,参见下图:

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

下面引用测试应用为 Reddit Sync 的不同场景下彩色和黑色模式功耗对比。(参考链接:m.zol.com.cn/article/489… )

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

FOSS

FOSS (Fidelity Optimized Signal Scaling,保真优化信号缩放)是芯片厂商提供的一种对 AMOLED 屏幕调节的低功耗方案。LCD 屏幕上对应的是 CABC (Content Adaptive Brightness Control,内容适应背光控制)。一方面降低屏幕亮度,一方面调节显示内容灰度值,从而使显示效果差异不大,由于降低了屏幕亮度,所以获取的功耗收益较大。一般大约是 0.2 小时左右,即平均可延长手机使用时间 0.2 小时左右。

已知的情况是厂商的 FOSS 方案在某些参数情况下会导致个别场景出现变色或闪烁问题。如果遇到未确认闪烁问题,在内部定位无法确认原因时,可以跟厂商咨询进行排除。

6.1.2.降低刷新率

目前市面上部分手机支持 60HZ,90HZ,120HZ,144HZ 等,高的刷新率带来了流畅度提高,用户的体验更好,但是功耗更高。 通常来讲在系统应用界面比如桌面,设置,刷新率会跟当前系统设置保持一致,而在具体应用中,刷新率会根据不同场景做调整。比如抖音,即使在高刷屏幕上,平台系统一般选择让抖音运行在 60HZ 刷新率,从而相对功耗较低。

针对不同的刷新率,PhoneArena 就做了一个比较有参考性的数据来验证这个观点。他们选取了两个品牌四款产品,都是高刷新率的机型,在同一条件下进行 60Hz 刷新率和 120Hz 刷新率的测试,结果 120HZ 刷新率下手机续航相比 60HZ 下的确缩短了至少 10%,即便是支持 90Hz 的一加 8 也是比 60HZ 刷新率要差。

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

七丶GPU

GPU 的优化思路主要在减少不必要的绘制或者降低绘制面积,这体现在更低的分辨率,更低的帧率,更少的绘制图层等方面。此外视频应用使用 SurfaceView 替换 TextureView 也有显著的功耗收益。对于复杂的运算,我们可以选择更高能效比的器件来进行,比如使用硬件绘制代替软件绘制,使用 NPU 代替 GPU 执行复杂算法,对整体功耗都有明显降低。

7.1.降低分辨率

应用低分辨率

通常该模式下游戏和特定应用一般以较低分辨率运行。缩小了 GPU 绘制区域和传输区域大小,降低了 GPU 和 CPU 以及传输 DDR 的功耗。功耗收益在游戏场景下比较大,线下测试特定平台下1080p->720p约20mA左右,1440p->720p约40mA左右。

其原理如下,应用图层在低分辨率下绘制,通过 HWC 通道放大到屏幕分辨率并跟其余图层合成后送显。

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

7.2.减少刷新区域

应用布局动画位置相近,布局出来一个较小的区域,绘制区域最小,刷新区域最小, 从而功耗最低。不同场景,收益不同。

如下图两种情况,可以看到左侧图,有 3 个动画区域(红色框住区域),最终形成的 Dirty 区域为大的红框区域,整个面积较大。而对比中间图,动画两个红色区域,经过运算后形成的 Dirty 大红框区域就较小,GPU 的绘制区域跟刷新的传输区域都较小,从而相对而言,功耗较低。从最右侧功耗数据图中可以看出收益较大。

可以在开发者选项中打开:设置 -> 开发者选项 -> 显示GPU视图更新,当刷新范围与动画范围明显不一致时便是动画布局不合理。这种情况需要具体到代码层面分析写法的问题并修改。

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

在抖音应用中,低绘制帧率可以通过在抖音内部主动降低动画等帧率实现。在抖音推荐界面音乐转盘动画和音符动画中降低帧率,可以显著的降低功耗。此外也可以通过厂商侧提供 soft vsync 实现 30HZ 绘制,这部分抖音与厂商合作,SurfaceFlinger 控制 APP vsync,降帧时 SurfaceFlinger vsync 输出降为 30fps,在特定条件下主动降低帧率,以延长使用时长。

7.4.帧率对齐

在抖音推荐页面中,通过视频和降低频率后的动画达到同步,可以实现整个界面以30HZ 绘制和刷新。 否则,如果视频30hz和动画30帧正好交错,最终形成的绘制/刷新频率还是60帧,没有达到最优。我们通过调节各种动画的绘制流程,将动画整体绘制对齐,整体帧率明显降低。

7.5.减少过度绘制

过度绘制(Overdraw)描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次重叠的 UI 结构里面,如果不可见的 UI 也在做绘制的操作,会导致某些像素区域被绘制了多次,同时也会浪费大量的 CPU 以及 GPU 资源。

可以通过如下来调试过度绘制:打开手机,设置 -> 开发者选项 -> 调试 GPU 过度绘制 -> 显示 GPU 过度绘制。过度绘制的存在会导致界面显示时浪费不必要的资源去渲染看不见的背景,或者对某些像素区域多次绘制,就会导致界面加载或者滑动时的不流畅、掉帧,对于用户体验来说就是 App 特别的卡顿。为了提升用户体验,提升应用的流畅性,优化过度绘制的工作还是很有必要做的。

抖音的 feed 页的过度绘制非常的严重,抖音存在 5 层过度绘制。下图左侧是优化前的过渡绘制情况,右侧是优化后的过度绘制情况,可以看出优化后明显改善。

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

BufferQueue 是 Android 图形架构的核心,其一侧是生产者,另一侧是消费者。从这方面看,SurfaceView 和 TextureView 的差异如下。容易看出,SurfaceView 流程更短,内存使用更少,也没有 GPU 绘制,功耗更省。

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

目前默认是开硬件加速的,可以通过设置 Activity,Application,窗口,View 等方式来指定软件绘制。如果应用需要单独指定某些场景的软件绘制方式,需要对性能、功耗等做好评估。参考链接:developer.android.com/guide/topic…

7.8.复杂算法用 NPU 代替 GPU

现在的较新的 SoC 平台都带有专门进行 AI 运算的 NPU 芯片,使用 NPU 代替 GPU 运行一些复杂算法,可以有效的节省 GPU 功耗。如视频的超分算法,可以给用户带来很好的体验。但是超分开启对 GPU 的耗电影响很大,在某些平台测试整机功耗可以高出 100mA,选择用 NPU 替换 GPU 是一种优化方式。

八丶CPU

CPU 的优化是功耗优化里最常见的,我们遇到的大部分的 CPU 异常都是出现了死循环。这里使用上面介绍过的功耗归因工具,都可以很容易的发现死循环问题。此外高频的耗时函数,效果和死循环类似,很容易让 CPU 大核跑到高频点,带来 CPU 功耗增加。另外一个典型的 CPU 问题,就是动画泄漏,泄漏动画大概能带来 20mA 的功耗增加。

由于 CPU 工作耗电很高,手机平台大多会增加各种低功耗的 DSP 来分担 CPU 的工作,减少耗电,如常见视频解码,使用硬解会有更好的功耗表现。

8.1.CPU 高负载优化

死循环治理

死循环是我们遇到的最明显的 CPU 异常,通常表现为某一个线程占满了一个大核。线程使用率达到了 100%,手机会很容易发热,卡顿。

这里举一个实际修复的死循环例子,在一段循环打包日志的代码逻辑里,所有 log打包完了,才会break跳出循环。当db query出现了异常,异常处理分支并没有做break,导致出现了死循环。

对于死循环治理,我们通过实际解决的问题,总结了几种常见的死循环套路。

高频耗时函数治理

除了死循环问题,我们遇到的另外一种常见的就是高频的耗时函数。通过线上监控 CPU 异常,我们也找到很多可优化的点。如 md5 压缩算法的耗时,正则表达式的不合理使用,使用 cmd 执行系统命令的耗时等。这种就 case by case 的修复,就有很不错的收益。

8.2.后台资源规范使用

Alarm,Wakelock,JobScheduler 的规范使用

最常见的后台 CPU 耗电就是对后台资源的不合理使用。Alarm 的频繁唤醒,wakelock 的长时间不释放,JobScheduler 的频繁执行,都会使 CPU 保持唤醒状态,造成后台耗电。这种行为很容易让系统判断应用为后台异常耗电,通常会被系统清理,或者发出高耗电提醒。

我们可以通过 dumpsys alarm & dumpsys power & dumpsys jobscheduler 查看相关的统计信息,也可以通过 BH 的后台统计来分析自身的使用情况。

参考绿盟的功耗标准,灭屏 Alarm 触发小于过 12 次/h,即 5min 一次,5min 一次在数据业务下可以保证长链接存活,厂商的后台功耗优化也通常会强制对齐 Alarm 为 5min 触发一次。

后台的 Partial Wakelock 通常会被重点限制,非可感知的场景(音乐,导航,运动)等会被厂商强制释放 wakelock。按照绿盟的标准,灭屏下每小时累计持锁小于 5min,从实际经验上看,持 Partial 锁超过 1min 就会被标为 Long 的 wakelock,如果是应用在后台无可感知业务并且频繁持锁,导致系统无法休眠的,系统会触发 forcestop 清理。

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战

图片来源:www.noobyard.com/article/p-e…

九丶 NETWORK

网络耗电是应用耗电的一个重要部分,一个数据包的收发,会同步拉动 CPU 和 Modem/WIFI 两大系统。由于 LTE 的 CDRX 特性(即没有数据包接收,维持一定时间的激活态,再进入睡眠,依赖运营商配置,通常为 10s),所以批量进行网络访问,减少频繁的网络唤醒对网络功耗很有帮忙。此外优化压缩算法,减少数据传输量也从基础上减少了网络耗电。

此外弱信号条件下的网络请求会提高天线的功率,也会触发频繁的搜网,带来更高的网络功耗。根据网络质量进行网络请求调度,提前预缓存网络资源,可以减少网络耗电。

9.1.长链接心跳优化

对于应用的后台 PUSH 来说,使用厂商稳定的 push 链路替代自己的长链接可以减少功耗。如果不能替换,也可以优化长链接保活的心跳,根据不同的网络条件动态的调整心跳。根据经验,数据业务下通常是 5min,WIFI 网络下通常可以达到 20min 或更久。

抖音对于长链接进行了的心跳优化,进入后台的长链接心跳时间间隔 [4min, 28min],初始心跳 4min。采用动态心跳试探策略,每次步进 2min,确定最大心跳间隔。

9.2.Doze 模式适配

由于系统对后台应用有多种网络限制策略,最常见的是 Doze 模式,手机灭屏一段时间后会进入 doze,限制非白名单应用访问网络,并在窗口期解除限制,窗口期为每 10min 放开 30s。所以在后台进行网络访问前要特别注意进行网络可用的判断,选择窗口期进行网络访问,避免因为被限网而浪费了 CPU 资源。

这里举一个 Doze 未适配的后台耗电例子,用户反馈抖音自上次手机充满电(24h)后,没有在前台使用过,耗电占比 31%,分析日志发现 I 在 Doze 限制网络期间,会触发轮询判断网络是否及时恢复,此逻辑在后台未适配 Doze 的窗口期模式,导致了后台频繁尝试网络请求带来的 CPU 耗电。

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战
  • 10-15 :1:30ma
  • 5-10:1:1.62ma
  • 0-5:1:1.36ma

10.2.调整音频参数

由于用户对音量的感受很明显,直接全局降低音量会带来不好的体验。厂商通常会针对不同的场景,设计不同的音频参数,如电影场景,游戏场景,导航场景,动态调节音频的高低频配置参数,兼顾了效果和功耗。

从这个角度出发,可以选择和厂商合作,根据播放视频的内容,精细化调整音频参数,如电影剪辑类型视频就使用电影场景的参数,游戏视频就切换为游戏场景的配置参数,从而达到用户无感调节音量节省功耗的目的。

十一丶 CAMERA

Camera 是功耗大户,尤其是高分辨率高帧率的录制会带来快速的功耗消耗和温升。经过线下测算,开播场景,Camera 功耗 200mA+,占整机的 25%以上。

优化Camera功耗的思路主要是从业务降级的角度上进行,如降低录制的分辨率,降低录制帧率等。之前抖音直播和生产端都是使用30帧,但最终只使用15帧,在开播端主动下调采集帧率,按需设置帧率为15帧,功耗显著降低了120ma。

十二丶 SENSOR

sensor 的典型功耗值很低,如我们常用到的 accelerometer(加速度计)的典型功耗只有 180uA。但 sensor 的开启会导致 cpu 的唤醒与负载增加,尤其是在应用退到后台,sensor 的滥用会显著增加待机功耗。可以在低电量时关闭不必要的 sensor,减少耗电。

十三丶GPS

精确度,频率,间隔是影响 GPS 耗电的三个主要因素。其中精度影响定位的工作模式,频率和间隔是影响工作时长,我们可以通过优化这三者来减少 GPS 的耗电

13.1.降低精度

Android 原生定位提供 GPS 定位和网络定位两种模式。GPS 定位支持离线定位,依靠卫星,没有网络也能定位,精度高,但功耗大,因需要开启移动设备中的 GPS 定位模块,会消耗较多电量。

Network 定位(网络定位),定位速度快,只要具备网络或者基站要求,在任何地方都可实现瞬间定位,室内同样满足;功耗小,耗电量小;但定位精度差,容易受干扰,在基站或者 WiFi 数量少、信号弱的地方定位质量较差,或者无法定位;必须连接网络才能实现定位。

我们可以在满足定位要求的情况下,主动使用低精度的网络定位,减少定位耗电,抖音在进入低功耗模式时,进行了 GPS 降级为网络定位,并且扩大了定位间隔。

13.2.降低频率&提高间隔

这里除了业务上主动控制频率与间隔外,还推荐使用厂商的定位服务。为了优化定位耗电,海外 gms 以及国内厂商都提供了位置服务 SDK,本质上是通过系统服务统一管理位置请求,根据电量,信号,请求方的延迟精度要求,进行动态调整,达到功耗与定位需求的平衡。提供了诸如被动位置更新,获取最近一次定位的位置信息,批量后台位置请求等低功耗定位能力。

developer.android.com/guide/topic… developer.huawei.com/consumer/cn…

十四丶低功耗模式

上述的优化措施,有些在常规模式下已经实施。但有一部分是有损用户体验的,我们选择在低电量场景下去做,降低功耗,减少用户的电量焦虑,获得用户在低电量下更多使用时长。

在低功耗模式预研中,我们列举了很多可做的措施,通过 AB 实验,我们去掉了业务负向的降级手段,比如亮度降低,音量降低等。此外在功能触发的策略上,我们通过对比了低电量弹窗提醒,设置里增加开关+Toast 提醒,以及低电量自动进入,最终选择了对用户体验最好的 30%电量无打扰自动进入的触发方式。

来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战 免费领取Android资料 来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战 微信名片 来一起看看抖音对于功耗优化是怎么做的;抖音Android性能优化实战 来源:初一十五啊

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年6月18日
下一篇 2022年6月18日

相关推荐