利用ADPF性能提示优化Android应用体验

news2024/10/28 6:23:29

Android Dynamic Performance Framework(ADPF)是google推广的一套用于优化散热以及CPU性能的动态性能框架。本文主要介绍其中的performance hint的部分。

1、为何引入ADPF

我们都知道,在大多数设备上,Android 会动态调整CPU的频率和核心类型。如果work load使用的CPU资源较多,那么提升CPU的频率,工作负载最终会移至性能更强的CPU核心上。如果work load使用的CPU资源较少,那么Android会减少资源分配。对于任务的负载,主流的有两种算法: PELT(Per-Entity Load Tracking)和WALT(Window Assist Load Tracking).  但是不管是那种负载统计方法,都需要采集过去一段时间内的线程运行情况,都存在一定的时间滞后性。

f6cecb5c6512acc7367c9a25f95919a2.png

图 1. 调节器可能需要大约 200 毫秒的时间来增加或降低 CPU 频率。

本文借鉴ADPF官网介绍文档里面的案例,如上图1,由于任务负载统计的累计需要一定的时间,一个任务要经过200ms才能运行到最高频率。以我们当前屏幕的刷新率60HZ为例,每一帧的完整绘制时间不超过33.3ms. 因此DCVS的这种的滞后性会导致我们调频不及时,带来图形绘制上的卡顿。

aeac2fd80cec3862a09e169ce7b13cdc.png

图2:CPU调频过慢导致的卡顿丢帧    

上图2是我们在实际性能分析过程中遇到的一个经典案例,我们可以看到QQ主线程在过去几帧的耗时并不长,但是某一帧因为工作负载的原因出现了长时间运行,CPU频率阶段性提升,最终错误了vsync,导致了丢帧卡顿。       

2、ADPF API描述

借助ADPF,应用或者游戏可以发送有关其性能和截止时间的额外信号。这个有助于系统更积极地磨合(改善性能),并降低在工作负载完成后迅速的调整时钟(节省电量)。在PerformanceHintManager.Session里面,我们可以看到如下几个暴露的API:

ADPF performance hint API

描述

close

Ends the current hint session.

关闭当前的提示session

reportActualWorkDuration(long actualDurationNanos)

Reports the actual duration for the last cycle of work.

上报上一次周期工作的的实际运行时长

reportActualWorkDuration(WorkDuration workDuration)

Reports the work duration for the last cycle of work.

上报上一次周期工作的的实际运行时长

setPreferPowerEfficiency(boolean enabled)

This tells the session that these threads can be safely scheduled to prefer power efficiency over performance.

现在主流移动处理器都是采用big-little架构,此API用于告诉系统这些相关的线程更加倾向于放置到性能核心上还是放到能效核心上

setThreads(int[] tids)

Set a list of threads to the performance hint session.

用于设置在当前session里面需要关注的关键线程

updateTargetWorkDuration(long targetDurationNanos)

Updates this session's target total duration for each cycle of work.

上报工作周期,一般匹配vsync周期。

下面我们来跟踪一下这些API在android源码里面是怎么使用案例吧。

在frameworks/base/libs/hwui/renderthread/HintSessionWrapper.cpp的init函数中,我们可以看到

通过createSessionInternal(manager, tids.data(), tids.size(), targetDurationNanos, SessionTag::HWUI)创建了一个session,其中tids分别是mUiThreadId跟mRenderThreadId。也就是核心关键线程分别是ui主线程以及render线程。这个熟悉android性能分析或者绘制流程的同学都知道,在hwui绘制里面,应用主线程以及render渲染线程是整个绘制链路中的核心线程。 

a7a9d72ef03245b498e0d6ff1d6970c7.png

reportActualWorkDuration用于在实际的绘制过程中,向ADPF上报每一帧的时机绘制耗时。这套framework框架最终依赖于平台对这些hint的最终反应,才能最终达到优化 performance的效果。                 

3、应用开发者如何使用ADPF

在google的ADPF官方文档里面也提到了Cocos、Unity、Unreal等游戏引擎采用ADPF来给android发送性能相关的细节信息,因为游戏的绘制跟游戏引擎具有很强的关联,区别与android上传统的hwui的绘制。

以unity为例https://docs.unity3d.com/Packages/com.unity.adaptiveperformance.google.android@1.2/manual/index.html

由于游戏引擎被众多的游戏应用所采用,在游戏引擎中使用ADPF不失为一个好的推广途径。unity引擎通过createHintSession 来创建一个hint session;通过reportActualWorkDuration来上报在实际一帧过程中所有相关参与到的线程的工作负载,当然最终对于CPU核心的频率调节,以及任务摆置到性能核心还是能效核心,这些都需要vendor平台厂商,或者android设备开发商对于这些hint进行操作系统层面的支持与优化。

由于游戏会有较高的工作负载以及发热的分享,文档介绍了关于thermal以及游戏gameMode相关的内容,不在本文的介绍范围之类,不再赘述。         

4、底层开发者如何支撑ADPF

那么设备开发商是如何支撑ADPF的呢,其中MTK做相比晚上一些。本文以MT6989的内核开源代码为例展开研究,忽略掉了从framework到kernel的中间native实现。在kernel/kernel_device_modules-6.1/drivers/misc/mediatek/performance/perf_ioctl/ioctl_powerhal.c文件中,我们看到了一些跟ADPF上层API比较对应的功能实现函数。    

176e38fef9db6db1d25d2cbdc5dede6a.png

从名字上看,这些函数是跟ADPF的框架API基本一一对应的。powerhal_adpf_create_session_hint_fp我们可以知道,对应着框架创建一个session;powerhal_adpf_report_actual_work_duration_fp 用于上报work duration

powerhal_adpf_set_threads_fp 用于上报核心线程。        

以powerhal_adpf_set_threads_fp为例,其对应的实现为adpf_set_threads函数。调用了adpf_notify_callback(ADPF_SET_THREADS, sid);函数。最终调用通过adpf_register_callback注册进来的callback函数。我们看到有两个地方进行了callback的注册,一个是sched,另外一个是fpsgo

adpf_register_callback(sched_adpf_callback);

adpf_register_callback(fpsgo_notify_adpf_hint);         

那么我们就想起看看sched以及fpsgo(MTK的一套私有的基于追帧的任务摆核与调频方案)针对powerhal_adpf_set_threads_fp的实现具体是什么。

先从scheduler开始。

在sched_adpf_callback函数中

fed6c7d598a561f0c0e30f68419039a8.png

我们可以看到sched的callback做了两件事情;

1.通过set_task_basic_vip把上报的关键线程设置为VIP线程(我们简单理解VIP为特权线程,可以优先进行任务调度来优化调度延迟。对应高通walt调度器里面的MVP线程)。针对VIP线程这里不对具体的技术细节展开描述。主要是为了降低线程的调度时延的。我们知道cfs调度类的进程,是基于vruntime的公平调度,在重载下,并不能保障相应线程的runnable的调度时延。

2.__set_task_to_group也是MTK的私有函数,通过将一些线程放到一个group里面,去针对整个group进行负载的统计与调频。group的概念并不是非常陌生,在高通的walt代码里面,可以看到related_thread_group的概念,在ios中也可以看到 thread group的概念。其实都是尽可能跳出linux原生调度器以task或者cpu为基础单位的负载统计,而是以业务涉及到的线程组为单位进行负载的统计。        

再回过头来看fpsgo针对线程上报的处理函数。在函数fpsgo_notifier_wq_cb_adpf_hint中

e619426cb1b978ec3feb139f3d24a3f1.png

依然可以看到fpsgo调用私有的函数,将上报的关键线程添加到fpsgo的依赖线程列表depency list里面(可以认为是fpsgo跟踪的关键线程),做后续的关键线程的负载跟踪以及uclamp针对关键线程的迁核与提频的处理。对于fpsgo的细节,本文不展开进行细节讨论,可以认为是一种针对绘制链路的关键线程的负载跟踪与调频调度的方案。         

5、对ADPF的一点感想    

本文以google的ADPF,简单的串联了一下在MTK平台上的相关代码。我们知道linux操作系统的一些底层机制存在一些机制上的弱点,这些弱点包括普通CFS进程无法保障调度延迟,PELT/WALT负载跟踪在负载波动时存在滞后性,DCVS调频依赖于历史统计数据。这些弱点在面向交互式设备上,无法快速的对用户的操作进行及时的响应。因此ADPF框架可以有效的将业务跟操作系统的机制连接在一起,通过主动的告诉参与到业务的核心线程、业务的工作周期,以及业务的资源述求等等hint来让操作系统的底层机制更好的为业务目标而服务。

从ADPF中,可以看到google在流畅性与功耗热上的一些探索,尝试将android的业务与linux的底层机制揉合成一个整体的这种意图与期望。从中我们也可以看到它借鉴了ios上的thread group与WIO(work interval object)的思路。当前ADPF的推广接入并不是十分理想,如webview、flutter等场景参与绘制链路的并不仅仅是应用主线程以及render渲染线程,更加需要通过ADPF框架来提供性能hint做好优化。与此同时,这样比较开发的接口,也可能导致被”有意“的使用,带来适得其反的效果,这也是需要注意的。        

        

名词缩写:

DCVS:Dynamic Clock and Voltage Scaling

ADPF:Android Dynamic Performance Framework

PELT:Per-entity Load tracing

WALT:Window assist load tracing

WIO:work interval object        

参考:

1.https://developer.android.com/games/optimize/adpf

2.https://github.com/oppo-source/android_kernel_modules_oppo_mt6989/tree/oppo_mt6989_u_14.0.1_oppo_find_x7

3.https://docs.unity3d.com/Packages/com.unity.adaptiveperformance.google.android@1.2/manual/index.html

7b2b1cbe6fa67aeeee7edfbf30c766a6.jpeg

Google VINTF机制经验总结

10分钟了解OPPO中间件容器化实践

2024年Arm最新处理器架构分析——X925和A725

8eb02b1192fb812c101e752a6973584d.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2225245.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简单的udp程序

文章目录 1. 预备知识1.1 源IP地址和目的IP地址1.2 端口号1.3 套接字初识1.4 tcp协议和udp协议简单认识1.5 网络字节序 2. udp程序2.1 创建套接字(socket)的系统调用2.2 bind()2.2.1 初始化一个sockaddr_in结构体2.2.2 inet_addr函数2.2.3 0.0.0.02.2.4 …

如何搭建AI智能化招聘平台?招聘系统源码与小程序开发技术方案探讨

本篇文章,小编将深入探讨如何搭建一个AI智能化招聘平台,分析其背后的招聘系统源码架构以及APP开发的技术方案。 一、AI智能化招聘平台的核心功能 在设计AI招聘平台时,必须考虑其核心功能,以确保平台具备高效的招聘能力和智能化的…

shodan4,挂黑网站查找,弱口令网站搜索

myip参数 shodan myip(查看自己的出口IP,哪个地址链接的公网)挂黑网站查找 我们今天看一看找一下,有些已经被黑的网站好吧,就是利用shodan查看一下哪些网站已经被黑了。 shodan search -limit 10 -fields ip_str,port http.title:hacked b…

iOS静态库(.a)及资源文件的生成与使用详解(OC版本)

引言 iOS静态库(.a)及资源文件的生成与使用详解(Swift版本)_xcode 合并 .a文件-CSDN博客 在前面的博客中我们已经介绍了关于iOS静态库的生成步骤以及关于资源文件的处理,在本篇博客中我们将会以Objective-C为基础语言…

十八、【智能体】数据库:未来科技的大脑

在上一篇中我们讲到了 **变量 ** , 变量 的作用是保存用户个人信息,让 Bot记住用户的特征,使回复更加个性化。 上一篇内容为:https://blog.csdn.net/qq_40585384/article/details/143272599 但变量有一个缺点——存储的信息太单…

【数据结构与算法】《Java 算法宝典:探秘从排序到回溯的奇妙世界》

目录 标题:《Java 算法宝典:探秘从排序到回溯的奇妙世界》一、排序算法1、冒泡排序2、选择排序3、插入排序4、快速排序5、归并排序 二、查找算法1、线性查找2、二分查找 三、递归算法四、动态规划五、图算法1. 深度优先搜索(DFS)2…

【Linux系统编程】——Linux入门指南:从零开始掌握操作系统的核心(指令篇)

文章目录 查看 Linux 主机 ip以及登录主机Linux基础文件操作指令man:查看命令的手册页,了解命令的详细用法。pwd:显示当前目录路径。cd:切换目录。ls:列出当前目录下的文件和文件夹。mkdir:创建新目录。 文…

ArrayList和Array、LinkedList、Vector 间的区别

一、ArrayList 和 Array 的区别 ArrayList 内部基于动态数组实现,比 Array(静态数组) 使用起来更加灵活: ArrayList 会根据实际存储的元素动态地扩容或缩容,而 Array 被创建之后就不能改变它的长度了。ArrayList 允许…

el-table相关的功能实现

1. 表格嵌套表格时&#xff0c;隐藏父表格的全选框 场景&#xff1a;当table表格设置复选&#xff08;多选&#xff09;功能时&#xff0c;如何隐藏表头的复选框&#xff0c;不让用户一键多选。 <el-table :header-cell-class-name"cellClass">// 表头复选框禁…

102. 管道漫游案例

通过一个轨迹线生成一个管道几何体&#xff0c;然后相机沿着该轨迹线移动&#xff0c;注意相机的方向要沿着轨迹线的切线方向&#xff0c;这样会形成一个管道漫游的效果。 管道几何体TubeGeometry、纹理贴图相机对象Camera的.position属性和.lookAt()方法 管道模型 课件源码“…

动态规划算法专题(九):完全背包问题

目录 1. 【模板】完全背包 1.1 算法原理 1.2 算法代码 1.3 空间优化 1.4 空间优化版本代码 2. 零钱兑换 2.1 算法原理 2.2 算法代码 3. 零钱兑换 II 3.1 算法原理 3.2 算法代码 4. 完全平方数 4.1 算法原理 4.2 算法代码 完全背包问题的初始化与 01 背包的初…

电动汽车与软件定义汽车(SDV)时代的汽车行业变革

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

LeetCode437. 路径总和 III(2024秋季每日一题 50)

给定一个二叉树的根节点 root &#xff0c;和一个整数 targetSum &#xff0c;求该二叉树里节点值之和等于 targetSum 的 路径 的数目。 路径 不需要从根节点开始&#xff0c;也不需要在叶子节点结束&#xff0c;但是路径方向必须是向下的&#xff08;只能从父节点到子节点&am…

.NET Core WebApi第3讲:第一个Web Api项目

一、.NEt Core 1、运行模板项目 1&#xff09;仍然有controllers&#xff0c;说明WebApi是基于MVC模式的&#xff0c;只是对比之下这里没有MVC中的views。 因为WebApi只会向前台发送数据&#xff0c;不会向前台发送HTML页面。 2、验证模板项目的api 1&#xff09;法1&#xf…

第12次CCF CSP认证真题解

1、最小差值 题目链接&#xff1a;https://sim.csp.thusaac.com/contest/12/problem/0 100分代码&#xff1a; #include <iostream> #include <algorithm> using namespace std; int main(int argc, char *argv[]) {int n;cin >> n;int a[1010],b[1010];f…

【模型学习】

https://zhuanlan.zhihu.com/p/522344841 from transformers import AutoTokenizer tokenizer AutoTokenizer.from_pretrained(model_checkpoint) tokenizer("男女主角亦有专属声优这一模式是由谁改编的&#xff1f;", "任天堂游戏谜之村雨城") { input_…

数通自学——计算机网络基础知识IP地址、局域网、广域网、NAT、端口映射、子网掩码、网关、IPV4、IPV6

计算机网络基础知识IP地址、局域网、广域网、NAT、端口映射、子网掩码、网关、IPV4、IPV6 一、IP地址1、概念引入2、概念3、组成及分类 二、局域网和广域网1、局域网2、广域网 三、NAT与端口映射四、公网IP、私网IP五、IPV4与IPV6 一、IP地址 1、概念引入 现在思考一个问题&a…

IntelliJ IDEA 查看类class的结构Structure轮廓outline窗口, 快捷键是Alt+7

IntelliJ IDEA 查看类class的结构Structure轮廓outline窗口, 快捷键是Alt7 idea的结构Structure窗口相当于Eclipse的outline 快捷键是: Alt7 或者点击左上角主菜单面包屑,打开主菜单 然后菜单找到-视图&#xff08;View&#xff09;→ 工具窗口&#xff08;Tool Windows&…

鸿蒙开发--点击下拉菜单,同时最下面出现遮罩层的实现方法

效果展示 实现 除去最上面的Naviation标题&#xff08;房源列表&#xff09;&#xff0c;该页面有两个SearchFilter搜索筛选&#xff08;包括其中的下拉菜单&#xff09;&#xff0c;RoomList房源列表 根目录容器 显然&#xff0c;两个组件之间存在覆盖关系&#xff0c;所以…

【密码学】全同态加密张量运算库解读 —— TenSEAL

项目地址&#xff1a;https://github.com/OpenMined/TenSEAL 论文地址&#xff1a;https://arxiv.org/pdf/2104.03152v2 TenSEAL 是一个在微软 SEAL 基础上构建的用于对张量进行同态加密操作的开源Python库&#xff0c;用于在保持数据加密的状态下进行机器学习和数据分析。 Ten…