利用ADPF性能提示优化Android应用体验
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). 但是不管是那种负载统计方法,都需要采集过去一段时间内的线程运行情况,都存在一定的时间滞后性。
图 1. 调节器可能需要大约 200 毫秒的时间来增加或降低 CPU 频率。
本文借鉴ADPF官网介绍文档里面的案例,如上图1,由于任务负载统计的累计需要一定的时间,一个任务要经过200ms才能运行到最高频率。以我们当前屏幕的刷新率60HZ为例,每一帧的完整绘制时间不超过33.3ms. 因此DCVS的这种的滞后性会导致我们调频不及时,带来图形绘制上的卡顿。
图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渲染线程是整个绘制链路中的核心线程。
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比较对应的功能实现函数。
从名字上看,这些函数是跟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函数中
我们可以看到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中
依然可以看到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
往
期
推
荐
Google VINTF机制经验总结
10分钟了解OPPO中间件容器化实践
2024年Arm最新处理器架构分析——X925和A725
相关文章:
利用ADPF性能提示优化Android应用体验
Android Dynamic Performance Framework(ADPF)是google推广的一套用于优化散热以及CPU性能的动态性能框架。本文主要介绍其中的performance hint的部分。 1、为何引入ADPF 我们都知道,在大多数设备上,Android 会动态调整CPU的频率和核心类型。如果work l…...
论文阅读 - Pre-trained Online Contrastive Learning for Insurance Fraud Detection
Pre-trained Online Contrastive Learning for Insurance Fraud Detection| Proceedings of the AAAI Conference on Artificial Intelligence 目录 摘要 Introduction Methodology Problem Formulation Pre-trained Model for Enhanced Robustness Detecting Network a…...
【最全基础知识2】机器视觉系统硬件组成之工业相机镜头篇--51camera
机器视觉系统中,工业镜头作为必备的器件之一,须和工业相机搭配。工业镜头是机器视觉系统中不可或缺的重要组成部分,其质量和性能直接影响到整个系统的成像质量和检测精度。 目录 一、基本功能和作用 二、分类 1、按成像方式分 2、按焦距分 3、按接口类型分 4、按应用…...
虚拟机WIN7安装PADS VX24 出现脚本故障 IPW213
用虚拟机安装WIN7,再开始安装PADS V24出现脚本故障IPW213 有去.NetFramework3.5 仍然没有效果 Download Microsoft .NET Framework 3.5 from Official Microsoft Download Center 最终用360驱动大师检测了下 发现有些必备组件没有安装,安装之后重启。 …...
Java正则表达式详解万字笔记内容丰富
正则表达式 1.1 正则表达式的概念及演示 在Java中,我们经常需要验证一些字符串,例如:年龄必须是2位的数字、用户名必须是8位长度而且只能包含大小写字母、数字等。正则表达式就是用来验证各种字符串的规则。它内部描述了一些规则,…...
文件属性与目录
⚫ Linux 系统的文件类型; 普通文件:存储数据,如文本文件、可执行文件等。 目录:用于组织文件和其他目录的特殊文件。 符号链接:指向另一个文件或目录的引用,类似于 Windows 中的快捷方式。 硬链接&#x…...
5G 基站SCTP
如何实现SCTP多归属链路对接 文章目录 前言一、SCTP是什么?二、lksctp三.sctp初始化四.绑定本端两个IP 五.与对端建链六.设置主要路径七.设置是否启用心跳八.关于防火墙的配置 总结 …...
MFC的SendMessage与PostMessage的区别
一、SendMessage 同步操作: SendMessage 是一个同步函数,它会将消息发送到指定的窗口,并等待该窗口的消息处理过程完成,然后返回。这意味着它会阻塞当前线程,直到消息处理完成。 直接调用: SendMessage 会…...
学习虚幻C++开发日志——基础案例(持续更新中)
官方文档:虚幻引擎C编程教程 | 虚幻引擎 5.5 文档 | Epic Developer Community | Epic Developer Community 1.物体上下起伏并旋转 1.1第一种写法 创建一个继承于Actor的类,并为新的Actor命名为FloatingActor,然后点击Create Class 重新…...
【CUDA代码实践03】m维网格n维线程块对二维矩阵的索引
文章目录 一、数据存储方式二、二维网格二维线程块三、二维网格一维线程块四、一维网格一维线程块 为了方便下次找到文章,也方便联系我给大家提供帮助,欢迎大家点赞👍、收藏📂和关注🔔!一起讨论技术问题&am…...
VSCode Qt6安装OpenSSL
报错 Could NOT find OpenSSL, try to set the path to OpenSSL root folder in thesystem variable OPENSSL_ROOT_DIR (missing: OPENSSL_CRYPTO_LIBRARYOPENSSL_INCLUDE_DIR SSL Crypto) (Required is at least version "3.0")问题确认 这个错误显示在Windows环境…...
JAVA学习-练习试用Java实现“定义一个用户类,包含用户名和密码”
问题: 定义一个用户类(User),包含用户名(username)和密码(password)属性,提供静态方法验证密码是否有效(长度至少为6),并提供getter和…...
大数据之VIP(Virtual IP,虚拟IP)负载均衡
VIP(Virtual IP,虚拟IP)负载均衡是一种在计算机网络中常用的技术,用于将网络请求流量均匀地分散到多个服务器上,以提高系统的可扩展性、可靠性和性能。以下是对VIP负载均衡的详细解释: 一、VIP负载均衡的基…...
鸿蒙网络编程系列38-Web组件文件下载示例
1. web组件文件下载能力简介 在本系列的第22篇文章,介绍了web组件的文件上传能力,同样的,web组件也具备文件下载能力,鸿蒙API提供了处理web组件下载事件的委托类型WebDownloadDelegate,该类型包括四个下载事件的回调接…...
Cisco Packet Tracer 8.0 路由器的基本配置和Telnet设置
文章目录 构建拓扑图配置IP地址配置路由器命令说明测试效果 构建拓扑图 1,添加2811路由器。 2,添加pc0。 3,使用交叉线连接路由器和pc(注意线路端口)。 4,使用配置线连接路由器和pc(注意线路…...
Flink系列之:学习理解通过状态快照实现容错
Flink系列之:学习理解通过状态快照实现容错 状态后端检查点存储状态快照状态快照如何工作?确保精确一次(exactly once)端到端精确一次 状态后端 由 Flink 管理的 keyed state 是一种分片的键/值存储,每个 keyed state…...
Linux 读者写者模型
1.背景概念 在编写多线程的时候,有一种情况是十分常见的。那就是,有些公共数据修改的机会比较少。相比较改写,它们读的机会反而高的多。这样就衍生出了读者写者模型,在这个模型中,有两类线程:读者和写者。读…...
JavaScript 的 axios 实现文件下载功能
用 JavaScript 的 axios 实现文件下载功能,咱们要分几个步骤来搞定它!最主要的部分是处理 二进制数据,可以生成一个进度检测,然后把它保存为文件。 文件名的获取二进制数据获取创建下载链接 const axios require(axios);const g…...
合合信息亮相2024中国模式识别与计算机视觉大会,用AI构建图像内容安全防线
近日,第七届中国模式识别与计算机视觉大会(简称“PRCV 2024”)在乌鲁木齐举办。大会由中国自动化学会(CAA)、中国图象图形学学会(CSIG)、中国人工智能学会(CAAI)和中国计…...
深度学习:匿名函数lambda函数的使用与numerical_gradient函数
背景: 假设我们有一个简单的线性回归模型,其损失函数是均方误差(MSE): class LinearModel:def __init__(self):self.W np.random.randn(1, 1) # 初始化权重def predict(self, x):return np.dot(x, self.W) # 线性预…...
PHP数据类型
几种常用的数据类型: String(字符串) Integer(整型) Float(浮点型) Boolean(布尔型) NULL(空值) Array(数组) Obje…...
2FA-双因素认证
双因素认证(2FA,Two-Factor Authentication)是一种提高安全性的方法,要求用户在登录或进行某些敏感操作时提供两种不同类型的身份验证信息。这种方法通过引入第二层验证,增加了账户被未经授权访问的难度。 项目结构 …...
解决 Python 中的 TypeError 错误
解决 Python 中的 TypeError 错误 在 Python 编程中,TypeError 是一种常见的错误,通常发生在尝试对不兼容的类型进行操作时。了解这个错误的原因以及如何有效解决它,对于提高代码的可靠性和可读性至关重要。本文将详细讨论 TypeError 的成因…...
快速学会C 语言基本概念和语法结构
😀前言 本篇博文是关于C 语言的基本概念和语法结构,希望你能够喜欢 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大家,您的满意是我的动力&a…...
Python酷库之旅-第三方库Pandas(172)
目录 一、用法精讲 791、pandas.UInt8Dtype类 791-1、语法 791-2、参数 791-3、功能 791-4、返回值 791-5、说明 791-6、用法 791-6-1、数据准备 791-6-2、代码示例 791-6-3、结果输出 792、pandas.UInt16Dtype类 792-1、语法 792-2、参数 792-3、功能 792-4、…...
Linux系统下minio设置SSL证书进行HTTPS远程连接访问
文章目录 1.配置SSL证书使用HTTPS访问2.MINIO SDK 忽略证书验证3.使用受信任的证书 1.配置SSL证书使用HTTPS访问 生成域名对应的SSL证书,下载Apache版本,我目前只发现Apache这个里面有对应的私钥和证书 私钥重命名为private.key证书重命名为public.crt&…...
npm 包的命名空间介绍,以及@typescript-eslint/typescript-eslint
npm 包的命名空间是一个重要的概念,用于组织和管理相关的包。通过命名空间,开发者可以避免命名冲突、增强包的可读性和可维护性。以下是关于 npm 命名空间的详细介绍,并以 typescript-eslint 作为示例。 1. 命名空间的结构 命名空间的格式为…...
ecovadis评估是什么,有什么提成自己评分等级
EcoVadis评估是一个企业社会责任(CSR)评级平台,旨在评估全球供应链的可持续性和道德情况。以下是对EcoVadis评估的详细介绍以及提升其评分等级的方法: 一、EcoVadis评估概述 定义:EcoVadis评估通过一系列框架评估公司…...
Vue3中ref、toRef和toRefs之间有什么区别?
前言 Vue 3 引入了组合式 API,其中 ref、toRef 和 toRefs 是处理响应式数据的核心工具。作为高级计算机工程师,我们有必要深入理解这些工具的细微差别,以便在实际项目中更加高效地管理状态。本文将详细解析 ref、toRef 和 toRefs 的区别&…...
react开发技巧
/* eslint-disable no-useless-escape */ const Validator { isEmail: /^([a-zA-Z0-9_\.\-])\(([a-zA-Z0-9\-])\.)([a-zA-Z0-9]{2,4})$/, // 校验邮箱 isPhoneNumber: /^1[3456789]\d{9}$/, // 手机号码验证 isMobileNumber: /^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/, //…...
自己做的网站能联网吗/沈阳关键词seo
一、先对ajaxFileUpload插件的语法参数进行讲解 原理:ajaxfileupload是通过监听iframe的onload方法来实现, 当从服务端处理完成后,就触发iframe的onload事件调用其绑定的方法,在绑定的方法中获取iframe中服务器返回的数据体&#…...
怎么申请免费网址/国内好的seo
Javascript中总有一些所谓的细节知识会让你目瞪口呆。前段时间,项目组新增一个需要,要求系统中所有显示时间的地方支持日期格式可定制什么事日期格式可定制呢,在平常呢,我们看到的时间格式一般是“yyyy-MM-dd”形式的,…...
网站建设与管理管理课程/网络营销策划活动方案
L1和L2正则都是比较常见和常用的正则化项,都可以达到防止过拟合的效果。L1正则化的解具有稀疏性,可用于特征选择。L2正则化的解都比较小,抗扰动能力强。 L2正则化 对模型参数的L2正则项为 即权重向量中各个元素的平方和,通常取1/2…...
做好公司网站/山西百度查关键词排名
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度后面…...
做网站软件ps/手机地图app下载安装
由于代码生成器有生成相应的spu查询列表接口,如下: 接口路径不变,修改该接口所调用的service层方法,加上相应查询参数,在SpuInfoService接口添加允许有筛选条件的方法,如下: /*** 根据条件筛选…...
大连手机自适应网站建设报价/如何在各大平台推广
前言 这一部分有三篇文章,主要是讲解go调度器的一些内容 三篇文章分别是: 理解golang调度之一 :操作系统调度理解golang调度之二 :Go调度器理解golang调度之三:并发简介 当我在解决一个问题尤其是新问题的时候,我开始不…...