Android系统“资源调度框架”
Android系统“资源调度框架”
一、一些问题的思考
“资源”是什么
计算机基础中提到,一套完整的计算机系统有三部分组成:应用程序、操作系统(OS)和计算机的硬件。
其中硬件又可分五大组成:控制器(CU)、运算器(ALU)、存储器(Memory)、输入设备(Input)和输出设备(Output)。
本文提到的“资源”指硬件的性能资源,所阐述的问题就是程序运行时分配到的硬件资源。
比如cpu的大小核心及数量,比如cpu、gpu、ddr、flash的运行频率。
“资源”和性能有什么关系
简单理解以cpu为例。程序的执行最终反映为cpu运行机器码,cpu时钟频率越高,相同时间内执行的语句就越多,自然程序运行越快。
如此就让人感觉到“性能”更强。
为什么需要资源调度
下面是两个生活化场景,可以思考一下。
1、同样一款游戏,同样的画质帧率设置下为啥有的机器卡卡的,有的比较流畅。
2、同样的一款游戏,为啥换什么配置的机器都感觉一个样。一样卡或者一样流畅。
开发者(系统厂商和应用开发者)有一致的目标:让应用程序流畅运行。但是应用直接操作控制cpu、gpu等硬件是不被允许的。
aosp中,cpu、gpu的资源调度默认还是内核在控制,系统框架间接控制。默认的策略考虑的是通用性,安全性。
但是现实针对具体的性能场景,往往需要更加精细的资源调度,这样在同样的硬件基础上能更充分的利用硬件资源提升用户体验。而不是“一核有难多核围观”
谁(进程)涉及到调度资源?
考虑以下典型场景
1、输入交互场景:cpu提频保证输入交互流畅
2、应用/游戏启动场景:cpu提频甚至绑定大核心,分配更多算力加速启动
3、下载时文件读写场景:提升flash频率,加速IO
4、游戏关键时刻:cpu、gpu提频,重点分配游戏进程
5、系统资源不够了:app得知资源不够主动裁减某些任务负载(比如降低画质),来保证自己的重要任务流畅
1和2平台系统侧来触发资源调度是比较合理的,但是3、4、5场景显然app才好知道,自己什么时候读写文件,什么时候游戏爆发团战,什么时候自己太猛让cpu、gpu快撑不住了,比如主动降低自己的画质保证流畅度。
从这两种角度来看,我们可以得知,资源调度、性能调优需要系统和应用的共同努力。系统和应用均需要获得资源调度接口。
现状是?
- AOSP
aosp在性能优化上不断进步,但是目前为止还是没有一套硬件的资源调度框架供给fwk与app,了解到的只有Framework中Powermanager#powerHint接口。
- 芯片厂商
芯片厂商在自己的平台上提供了基础的资源调度框架,像高通的perfLock,MTK的PerfService,提供了基础的cpu、gpu资源调度入口。
但这仅针对他们自己的芯片硬件如cpu、gpu。不包含其他厂商的硬件资源例如存储flash,并且是系统级别的接口,是给手机厂商用的,没有针对第三方应用提供一套SDK方案。
并且芯片平台之间这些框架是不通用的哈哈哈。
-
结论
aosp和芯片厂商release出的代码,目前没有现成的一套体系,让系统框架或app来控制底层硬件运行性能,包括不限于cpu,gpu,内存,io,网络。
手机厂商实现一套自己的资源调度框架是必选项。
我们的需求
从上面的问题以及思考、讨论中,使得我们的需求,诉求轮廓逐渐清晰:直接控制系统资源,直接获取系统运行状态。
我们要控制cpu的频率及运行的核心
我们要控制gpu的频率
我们要控制ddr、Flash的频率
我们要得知当前系统的压力
构思一下软件架构
系统进程和app进程都要用,java和native都要用。
那么要给app提供sdk,比如ndk、java lib的编译依赖
要给系统框架提供系统服务接口,java系统服务和native系统服务。
由于本架构是用于沟通硬件的,所以fwk里仅做鉴权和请求简单分解,真正的实现最好放到native或者更进一步放到内核里,避免java层native层多份实现
为了时效性可以整到单独的进程里,而不是放在system_server中。
下图是个示意图
图:资源调度软件架构示意图
有了这套资源调度框架,就能直接控制cpu等系统资源和接收系统状态了。
需要考虑接口的可移植性,不同芯片平台之间、不同android版本之间。除了目前常用的,还要对其他未来可能的硬件资源创造方便的增删接口。
还需要考虑到鉴权和策略控制,谁可以用和什么情况下允许用、时长频次等兜底策略。
二、目前国内手机厂商的做法调查
当前时间:2021-07
你抄我呀,我抄你,友商之间甜蜜蜜。
ov米差不多,华为只提供c的api。
然后ov米的接口风格是做的更少,直接把提频绑核放权给应用。而华为选择做的更多,给应用的是设置帧率、设置场景这种概念性接口,真正分配多少硬件资源由系统决定。
下面一起来瞅一瞅。
华为-计算加速服务-性能加速库
官网链接:华为计算加速服务
华为计算加速服务(HUAWEI Accelerate Kit,简称Acc Kit)支持多线程库和性能加速库,可实现高效的多线程加速能力和性能加速能力。
性能加速库是Acc Kit中的性能加速模块,它为您提供了设置显示帧率、设置关键线程、监听系统状态等硬件能力相关的接口。性能加速库允许您深度参与华为硬件平台的性能调度,使您能够更有效地利用华为平台的硬件能力。通过性能加速库自主控制性能参数,可使硬件响应更及时、更准确,能有效解决应用在部分场景的卡顿、掉帧等问题,同时又避免了低负载场景的性能过剩,最大程度提升整机能效比。
场景介绍
典型场景 | 策略描述 |
---|---|
高负载场景 | 游戏渲染场景下,通过设置关键线程保证用户线程的资源调度优先级,使得用户添加的线程优先被系统调用。 |
负载突变场景 | 通过系统性能监控接口,您更容易预知负载变化,及时通知硬件提高刷新率,使应用启动更快,游戏运行更流畅。 |
低刷新率场景 | 导航场景,通知硬件降低刷新率,切换到导航内动画时及时提高刷新率,在不影响用户体验情况下维持较低功耗。 |
混合场景 | 普通应用内视频播放场景中降低刷新率,滑动时提高刷新率,获取最佳效果和能效比。 |
PerfGeniusApi
Public Constructor Summary
Public Destructor Summary
Public Method Summary
PerfGeniusApi
~ PerfGeniusApi
Init
GetApiVersion
SetFrameRate
ResetFrameRate
GetCurrentFrameRate
GetSupportedFrameRate
SetScene
GetPerformanceLevel
AddKeyThreads
RemoveKeyThreads
RegisterSystemEventCallback
UnRegisterSystemEventCallback
RegisterPerformanceTracer
UnRegisterPerformanceTracer
GetPerfGeniusApiHandle
DeletePerfGeniusApiHandle
小米-应用加速器(MiBridge)
官网链接:应用加速器(MiBridge)介绍
框架
MiBridge是提供给应用接入到系统的一个接口
• 轻量级,JAR包,大小只有几kb。
• 低成本,与系统间连接采用Binder通信机制
API
boolean checkDebugPermission(Context context, String pkg, int uid, String auth_key)
boolean checkPermission(String pkg, int uid)
int requestCpuHighFreq(int uid, int level, int timeoutms)
int cancelCpuHighFreq(int uid)
int requestThreadPriority(int uid , int req_tid, int timeoutms)
int cancelThreadPriority (int uid , int req_tid)
requestGpuHighFreq,requestIOHighFreq,requestMemory,requestNetwork等
OPPO-HyperBoost
官网链接:HyperBoost介绍
应用场景
1)系统资源调度:关键使用场景下通知系统及时分配合理资源,保证应用流畅运行。
2)4D振感:支持多种精细的线性马达波形振感,开发者可以通过传入波形序号直接调用振动,带来更精彩的应用体验。
3)智能帧率(敬请期待):根据应用场景智能调节帧率,动态调整帧率策略,预防卡顿。
工作原理框架
通用接口说明
API原型 | API说明 |
---|---|
public HyperBoostUnitClient getHyperBoostClient(Context context) | 功能:初始化SDK,过程中完成鉴权和回执 参数:context:传入Activity上下文 |
public int getVersion() | 功能:获取SDK版本号,如1.0.1 sdk的版本号为100001 |
public boolean registerClient() | 功能:初始化HyperBoost引擎,需要在鉴权成功回调中使用 |
public boolean registerNotifier(HyperBoostCallback callback) | 功能:注册温控警报回调 参数:callback:用于温控回调的标准接口类实现 |
public boolean specificAction(String info) | 功能:针对应用特调优化场景预留接口,适用于商务对接过的三方应用,双方协定优化方案和通信协议,调用此接口通知服务端 参数:info:用于双方特调优化的通信的协议内容 |
普通应用接口说明
API原型 | API说明 |
---|---|
public boolean appBootCompleted() | 功能:应用冷启动时手机系统默认会有一段时间的加速,APP启动逻辑完成时若调用该接口通知系统,手机系统恢复一般状态,可以减少系统功耗。 |
public boolean appActionLoading(int loadTime, int level) | 功能:在应用加载等重负载场景下,调用此接口可以将系统性能在一定时间内拉高,为应用分配更大的系统资源,减少用户等待。为防止滥用造成功耗问题,单次调用最长加速时长为10秒,调用间隔最短为30秒。 参数: loadTime:CPU提频时长,单位ms,最大有效值10000 level:提频等级,分为三级,提频力度依次递增,应用按需调用。 可传入参数: HyperBoostCommonUtil.CPU_BOOST_LEVEL_COMMON; HyperBoostCommonUtil.CPU_BOOST_LEVEL_HIGH; HyperBoostCommonUtil.CPU_BOOST_LEVEL_STRONG; |
public boolean appActionBurst(int burstTime, int level) | 功能:对于短时间内负载较大的操作,可调用此接口,短时间内将CPU性能拉高。防止滥用造成功耗问题,单次调用最长加速时长为1秒,调用间隔最短为3秒。 参数: burstTime:CPU提频时长,单位ms,最大有效值1000 level:同appActionLoading方法 |
public boolean appActionDdr(int burstTime, int level) | 功能:短时间内提高内存读写速度和传输效率。防止滥用造成功耗问题,单次调用最长加速时长为1秒,调用间隔最短为3秒。 参数:burstTime:DDR提频时长,单位ms,最大有效值1000 level:暂不生效,可默认传HyperBoostCommonUtil.DDR_BOOST_LEVEL_COMMON; |
public boolean appActionGpu(int burstTime, int level) | 功能:短时间内拉高GPU工作频率,适用于应用画面渲染、页面切换等场景。防止滥用造成功耗问题,单次调用最长加速时长为1秒,调用间隔最短为3秒。 参数: burstTime:GPU提频时长,单位ms,最大有效值1000 level:暂不生效,可默认传HyperBoostCommonUtil.GPU_BOOST_LEVEL_COMMON; |
public boolean appActionEnd() | 功能:标识应用重负载场景结束,暂时不需要性能提升,系统将恢复正常状态,降低功耗。 |
public boolean appActionBind(int tid, boolean isBind) | 功能:传入线程id,系统将保障该线程运行在大核或超大核上。适用于应用负载较重,耗时较长的线程场景,如音视频类应用的视频编解码线程。 参数: tid: 需要绑定大核的线程id,需传入android系统级线程id isBind:传入HyperBoostCommonUtil.BIND_GOLD_CORE表示绑定大核,传入HyperBoostCommonUtil.UNBIND_GOLD_CORE表示解绑大核; |
游戏应用接口说明
API原型 | API说明 |
---|---|
public boolean gameBootCompleted() | 功能:游戏冷启动时手机系统默认会有一段时间的加速,游戏启动逻辑完成时若调用该接口通知系统,手机系统恢复一般状态,可以减少系统功耗。 |
public boolean gameSceneStart() | 功能:标识游戏开始。为了保持游戏期间性能稳定,通过调用该接口通知手机系统已正式开始打游戏,这时手机系统会开启触摸屏灵敏度优化、自动追帧等优化策略,从而使游戏性能更加稳定 |
public boolean gameSceneEnd() | 功能:标识游戏结束。在游戏结束或者回到游戏大厅时调用该接口,这时手机系统会关闭上述的触摸屏优化等优化策略,从而减少不必要的功耗,提升手机续航。 |
public boolean gameActionLoading(int loadTime, int level) | 功能:在游戏地图加载等重负载场景下,调用此接口可以将系统性能在一定时间内拉高,为应用分配更大的系统资源,减少用户等待。为防止滥用造成功耗问题,单次调用最长加速时长为30秒,调用间隔最短为60秒。 参数: loadTime:CPU提频时长,单位ms,最大有效值30000 level:提频等级,分为三级,提频力度依次递增,应用按需调用。 可传入参数: HyperBoostCommonUtil.CPU_BOOST_LEVEL_COMMON; HyperBoostCommonUtil.CPU_BOOST_LEVEL_HIGH; HyperBoostCommonUtil.CPU_BOOST_LEVEL_STRONG; |
public boolean gameActionBurst(int burstTime, int level) | 功能:对于短时间内负载较大的操作,可调用此接口,短时间内将CPU性能拉高。防止滥用造成功耗问题,单次调用最长加速时长为1秒,调用间隔最短为3秒。 参数: burstTime:CPU提频时长,单位ms,最大有效值1000 level:同appActionLoading方法 |
public boolean gameActionDdr(int burstTime, int level) | 功能:短时间内提高内存读写速度和传输效率。防止滥用造成功耗问题,单次调用最长加速时长为1秒,调用间隔最短为3秒。 参数: burstTime:DDR提频时长,单位ms,最大有效值1000 level:暂不生效,可默认传HyperBoostCommonUtil.DDR_BOOST_LEVEL_COMMON; |
public boolean gameActionGpu(int burstTime, int level) | 功能:短时间内拉高GPU工作频率,适用于游戏画面渲染、页面切换等场景。防止滥用造成功耗问题,单次调用最长加速时长为1秒,调用间隔最短为3秒。 参数: burstTime:GPU提频时长,单位ms,最大有效值1000 level:暂不生效,可默认传HyperBoostCommonUtil.GPU_BOOST_LEVEL_COMMON; |
public boolean gameActionEnd() | 功能:标识游戏重负载场景结束,暂时不需要性能提升,系统将恢复正常状态,降低功耗。 |
public boolean gameActionBind(int tid, boolean isBind) | 功能:传入线程id,系统将保障该线程运行在大核或超大核上。适用于游戏负载较重,耗时较长的线程场景,比如在地图资源加载的时候,配合提频一起使用。 参数: tid: 需要绑定大核的线程id,需传入android系统级线程id isBind:传入HyperBoostCommonUtil.BIND_GOLD_CORE表示绑定大核,传入HyperBoostCommonUtil.UNBIND_GOLD_CORE表示解绑大核; |
VIVO-Multi-turbo
官网链接:Multi-turbo SDK介绍
1、Multi-turbo SDK介绍
Multi-turbo SDK支持游戏应用和普通应用,普通应用在某些关键场景下可通过Multi-turbo SDK提供的接口,通知手机系统及时分配合理的系统资源,保障应用的流畅运行。游戏应用可以给系统提供精准的场景、设置等信息,系统可给游戏应用反馈系统状态等,利用这些信息双方可以更好的协作,更进一步改善玩家的游戏体验。
2、工作原理
开发者在需要的场景下,调用合适的Multi-turbo SDK提供的接口,手机系统层接受到相应需求,快速分配合理的系统资源,从而使应用运行更流畅;同时应用可注册对应系统状态回调,系统可以为注册系统回调的应用反馈对应系统状态信息,应用也可根据系统状态信息做一些相应调整,从而达到更好的效果。
API
public boolean checkPermission(String code)
public void appShortTurbo(int duration, int level)
public void appLongTurbo(int duration, int level)
public void appTurboEnd()
public void gameLongTurbo(int duration)
public void gameShortTurbo(int duration)
public void gameTurboEnd()
public void gameSceneStart()
public void gameSceneEnd()
public void updateGameInfo(String infoJson)
public String getPhoneInfo(int type)
public void registerCallBack(CallBack callBack, int flags)
三、最后
第一章的现状有提到,实现一套自己的资源调度框架是手机厂商的必经之路。
技术架构和核心方法上难点不大,只是copy一套系统服务和封装内核接口。
重点还是这些接口使用,因为涉及到全局的性能,所以完善的测试是必要的。
四、资料
本文来自博客园,作者:秋城,转载请注明原文链接:https://www.cnblogs.com/wanghongzhu/p/14994460.html