在MTK芯片上如何控制CPU的核数和频率-MTK PerfService
来源:互联网 发布:svm算法 july 编辑:程序博客网 时间:2024/04/30 05:26
在MTK芯片上如何控制CPU的核数和频率-MTK PerfService
一句话:PerfService就是用来调整CPU/GPU资源的。对于老的API,可以更简单地讲就是调CPU核数和CPU频率的。
PerfService简介
kernel中实现了两个driver,一个负责控制开关CPU的核数,叫做hot-plug驱动,另一个负责调整CPU的频率,叫做DVFS驱动。
kernel中的driver会根据系统的负载情况下,自动调整使用几个CPU和调整CPU频率。如果负载高了,提高频率,或者多开几个核,或者开大核。如果负载降下去了,就可以关大核,关核,降频。
虽然现在的自动调频和调核的策略已经定义了很多,也在不断地完善,但是有两个问题:一是总有覆盖不到的情况,或者干脆就是互相矛盾的需求导致策略冲突。二是自动调度都是后知后觉的,只有发现负载上来了或者降下去了,才来做负载调节,需要一定的时间。这样,要么是效率不够,要么是功耗无谓地消耗掉。
PerfService就是一个在用户空间来主动调节系统能力的服务。
C/C++调用PerfService
步骤
- 动态加载libperfservicenative.so
- 注册用户场景PerfServiceNative_userReg/PerfServiceNative_userRegBigLittle/PerfServiceNative_userRegScn
- 激活用户场景PerfServiceNative_userEnable
- 执行用户场景
- 反激活用户场景PerfServiceNative_userDisable
- 退出进程之前反注册PerfServiceNative_userUnreg/PerfServiceNative_userUnregScn
老API的步骤
老API只能对CPU做调度,但是好处是可以直接指定开几个核,频率调到多少,还可以控制开大核还是小核。
- PerfServiceNative_userReg可以指定几个核和多高的频率
- PerfServiceNative_userRegBigLittle还可以用来指定调度大小核
- PerfServiceNative_userEnable用来激活上面注册的场景,PerfServiceNative_userEnableTimeout可以指定激活的超时时间
- PerfServiceNative_userDisable用来反激活
- PerfServiceNative_userUnreg反注册
新API的步骤
新的API也可以调节GPU,但是采用的方式要复杂一些,就不再像老API一样直接指定核和频率了,需要定义配置
- PerfServiceNative_userRegScn:没有参数,直接注册就好
- PerfServiceNative_userRegScnConfig:用这个函数去真正指定配置
- PerfServiceNative_userEnable/PerfServiceNative_userEnableTimeout:跟老API没有区别
- PerfServiceNative_userDisable:还是老的API
- PerfServiceNative_userUnregScn:反注册
老API开发指南
指定核和频率PerfServiceNative_userReg
定义一个需要scn_core个核,scn_freq频率运行的任务
原型:
int PerfServiceNative_userReg(int scn_core, int scn_freq);
定义于:/mediatek/proprietary/hardware/perfservice/perfservicenative/PerfServiceNative.h
参数:
* scn_core:开多少个核
* scn_freq:频率调整到多少。如果只是希望多开几个核或者少开几个核,并不关注频率的话,可以置成0.
返回值:
* -1:失败
* other:handler,用于后续的操作
注册指定大核小核PerfServiceNative_userRegBigLittle
定义一个需要scn_core个核,scn_freq频率运行的任务
原型:
int PerfServiceNative_userRegBigLittle(int scn_core_big, int scn_freq_big,int scn_core_little, int scn_freq_little);
定义于:/mediatek/proprietary/hardware/perfservice/perfservicenative/PerfServiceNative.h
参数:
* scn_core_big:开多少个核
* scn_freq_big:频率调整到多少
* scn_core_little:开多少个核
* scn_freq_little:频率调整到多少
返回值:
* -1:失败
* other:handler
反注册
在退出进程之前需要进行反注册
原型:
void PerfServiceNative_userUnreg(int handle);
激活和反激活
注册了之后也不是一直用啊,用的时候再打开吧,使用PerfServiceNative_userEnable。如果一旦忧心有可能出exception之类的流程不能保证走到PerfServiceNative_userDisable的话,也可以加个超时,调用PerfServiceNative_userEnableTimeout.
原型:
void PerfServiceNative_userEnable(int handle);void PerfServiceNative_userDisable(int handle);void PerfServiceNative_userEnableTimeout(int handle, int timeout);void PerfServiceNative_userEnableTimeoutMs(int handle, int timeout);
参数:
* handle: 注册成功后返回的那个
* timeout: PerfServiceNative_userEnableTimeout是以秒为单位的超时时间,PerfServiceNative_userEnableTimeoutMs则以毫秒为单位。
新API开发指南
获取系统能力
int PerfServiceNative_userGetCapability(int cmd);
参数:
* cmd: 请参见下面的枚举值:
enum { CMD_GET_CPU_FREQ_LEVEL_COUNT = 0, CMD_GET_CPU_FREQ_LITTLE_LEVEL_COUNT = 1, CMD_GET_CPU_FREQ_BIG_LEVEL_COUNT = 2, CMD_GET_GPU_FREQ_LEVEL_COUNT = 3, CMD_GET_MEM_FREQ_LEVEL_COUNT = 4,};
- CMD_GET_CPU_FREQ_LEVEL_COUNT:获取CPU频率级别
- CMD_GET_CPU_FREQ_LITTLE_LEVEL_COUNT:获取小核CPU频率级别
- CMD_GET_CPU_FREQ_BIG_LEVEL_COUNT:获取大核CPU频率级别
- CMD_GET_GPU_FREQ_LEVEL_COUNT:获取GPU频率级别
- CMD_GET_MEM_FREQ_LEVEL_COUNT:获取内存频率级别
注册
因为新的API还需要指定配置,所以注册获取handle就不需要参数了。
原型:
int PerfServiceNative_userRegScn();
反注册
反注册PerfServiceNative_userRegScn注册的handle。注意,跟PerfServiceNative_userUnreg不一样啊。
void PerfServiceNative_userUnregScn(int handle);
配置
原型:
void PerfServiceNative_userRegScnConfig(int handle, int cmd, int param_1, int param_2, int param_3, int param_4);
参数:
* handle:PerfServiceNative_userRegScn注册的handle。
* cmd:命令
* param_1, param_2, param_3, param_4:根据命令不同的参数
命令请参见下面的枚举:
enum { CMD_SET_CPU_CORE_MIN = 0, CMD_SET_CPU_CORE_MAX = 1, CMD_SET_CPU_CORE_BIG_LITTLE_MIN = 2, CMD_SET_CPU_CORE_BIG_LITTLE_MAX = 3, CMD_SET_CPU_FREQ_MIN = 4, CMD_SET_CPU_FREQ_MAX = 5, CMD_SET_CPU_FREQ_BIG_LITTLE_MIN = 6, CMD_SET_CPU_FREQ_BIG_LITTLE_MAX = 7, CMD_SET_GPU_FREQ_MIN = 8, CMD_SET_GPU_FREQ_MAX = 9, CMD_SET_MEM_FREQ_MIN = 10, CMD_SET_MEM_FREQ_MAX = 11, CMD_SET_VCORE = 12, CMD_SET_SCREEN_OFF_STATE = 13, CMD_SET_CPUFREQ_HISPEED_FREQ = 14, CMD_SET_CPUFREQ_MIN_SAMPLE_TIME = 15, CMD_SET_CPUFREQ_ABOVE_HISPEED_DELAY = 16,};
- CMD_SET_CPU_CORE_MIN:设置最少核数.参数1个 - param_1:核数
- CMD_SET_CPU_CORE_MAX:设置最大核数.参数1个 - param_1:核数
- CMD_SET_CPU_CORE_BIG_LITTLE_MIN:设置最少大小核数.参数2个 - param_1:大核数,param_2:小核数
- CMD_SET_CPU_CORE_BIG_LITTLE_MAX:设置最大大小核数.参数2个 - param_1:大核数,param_2:小核数
- CMD_SET_CPU_FREQ_MIN:设置最低频率.参数1个 - param_1:频率
- CMD_SET_CPU_FREQ_MAX:设置最高频率.参数1个 - param_1:频率
- CMD_SET_CPU_FREQ_BIG_LITTLE_MIN:设置最低大小核数.参数2个 - param_1:大核频率,param_2:小核频率
- CMD_SET_CPU_FREQ_BIG_LITTLE_MAX:设置最高大小核数.参数2个 - param_1:大核频率,param_2:小核频率
- CMD_SET_GPU_FREQ_MIN:设置GPU最低频率级别,参数1个 - param_1:频率级别
- CMD_SET_GPU_FREQ_MAX:不支持
- CMD_SET_MEM_FREQ_MIN:不支持
- CMD_SET_MEM_FREQ_MAX:不支持
- CMD_SET_VCORE:设置图形模式,参数1个:DRAM模式:0-默认模式,1-低功耗模式,2-还是默认模式,3-高性能模式
- CMD_SET_SCREEN_OFF_STATE:设置关屏模式,一个参数,模式值。0-关屏无效,1-关屏有效,2-关屏暂停,打开恢复
- CMD_SET_CPUFREQ_HISPEED_FREQ:设置高速频率,一个参数。
- CMD_SET_CPUFREQ_MIN_SAMPLE_TIME:设置最小采样值,一个参数。
- CMD_SET_CPUFREQ_ABOVE_HISPEED_DELAY:设置above speed hispeed,一个参数。
开关屏的参数,请使用下面的枚举值:
enum { SCREEN_OFF_DISABLE = 0, SCREEN_OFF_ENABLE = 1, SCREEN_OFF_WAIT_RESTORE = 2,};
Java调用PerfService
步骤
- import IPerfServiceWrapper和PerfServiceWrapper
- 注册用户场景IPerfServiceWrapper.userReg
- 激活用户场景IPerfServiceWrapper.userEnable
- 执行用户场景
- 反激活用户场景IPerfServiceWrapper.userDisable
- 反注册用户场景IPerfServiceWrapper.userUnreg
IPerfServiceWrapper定义于
/frameworks/base/core/java/com/mediatek/perfservice/IPerfServiceWrapper.java
老API的步骤
老API只能对CPU做调度,但是好处是可以直接指定开几个核,频率调到多少,还可以控制开大核还是小核。
- IPerfServiceWrapper.userReg可以指定几个核和多高的频率
- IPerfServiceWrapper.userRegBigLittle还可以用来指定调度大小核
- IPerfServiceWrapper.userEnable用来激活上面注册的场景,IPerfServiceWrapper.userEnableTimeout可以指定激活的超时时间
- IPerfServiceWrapper.userDisable用来反激活
- IPerfServiceWrapper.userUnreg反注册
新API的步骤
新的API也可以调节GPU,但是采用的方式要复杂一些,就不再像老API一样直接指定核和频率了,需要定义配置
- IPerfServiceWrapper.userRegScn:没有参数,直接注册就好
- IPerfServiceWrapper.userRegScnConfig:用这个函数去真正指定配置
- IPerfServiceWrapper.userEnable/IPerfServiceWrapper.userEnableTimeout:跟老API没有区别
- IPerfServiceWrapper.userDisable:还是老的API
- IPerfServiceWrapper.userUnregScn:反注册
老API开发指南
指定核和频率PerfServiceNative_userReg
定义一个需要scn_core个核,scn_freq频率运行的任务
原型:
public int userReg(int scn_core, int scn_freq);
参数:
* scn_core:开多少个核
* scn_freq:频率调整到多少。如果只是希望多开几个核或者少开几个核,并不关注频率的话,可以置成0.
返回值:
* -1:失败
* other:handler,用于后续的操作
注册指定大核小核PerfServiceNative_userRegBigLittle
定义一个需要scn_core个核,scn_freq频率运行的任务
原型:
public int userRegBigLittle(int scn_core_big, int scn_freq_big, int scn_core_little, int scn_freq_little);
参数:
* scn_core_big:开多少个核
* scn_freq_big:频率调整到多少
* scn_core_little:开多少个核
* scn_freq_little:频率调整到多少
返回值:
* -1:失败
* other:handler
反注册
在退出进程之前需要进行反注册
原型:
public void userUnreg(int handle);
激活和反激活
注册了之后也不是一直用啊,用的时候再打开吧,使用PerfServiceNative_userEnable。如果一旦忧心有可能出exception之类的流程不能保证走到PerfServiceNative_userDisable的话,也可以加个超时,调用PerfServiceNative_userEnableTimeout.
原型:
public void userEnable(int handle);public void userEnableTimeout(int handle, int timeout);public void userEnableTimeoutMs(int handle, int timeout_ms);public void userDisable(int handle);
参数:
* handle: 注册成功后返回的那个
* timeout: PerfServiceNative_userEnableTimeout是以秒为单位的超时时间,PerfServiceNative_userEnableTimeoutMs则以毫秒为单位。
新API开发指南
获取系统能力
public int userGetCapability(int cmd);
参数:
* cmd: 请参见下面的常量值:
public static final int CMD_GET_CPU_FREQ_LEVEL_COUNT = 0;public static final int CMD_GET_CPU_FREQ_LITTLE_LEVEL_COUNT = 1;public static final int CMD_GET_CPU_FREQ_BIG_LEVEL_COUNT = 2;public static final int CMD_GET_GPU_FREQ_LEVEL_COUNT = 3;public static final int CMD_GET_MEM_FREQ_LEVEL_COUNT = 4;
- CMD_GET_CPU_FREQ_LEVEL_COUNT:获取CPU频率级别
- CMD_GET_CPU_FREQ_LITTLE_LEVEL_COUNT:获取小核CPU频率级别
- CMD_GET_CPU_FREQ_BIG_LEVEL_COUNT:获取大核CPU频率级别
- CMD_GET_GPU_FREQ_LEVEL_COUNT:获取GPU频率级别
- CMD_GET_MEM_FREQ_LEVEL_COUNT:获取内存频率级别
注册
因为新的API还需要指定配置,所以注册获取handle就不需要参数了。
原型:
public int userRegScn();
反注册
反注册PerfServiceNative_userRegScn注册的handle。注意,跟PerfServiceNative_userUnreg不一样啊。
原型:
public void userUnregScn(int handle);
配置
原型:
public void userRegScnConfig(int handle, int cmd, int param_1, int param_2, int param_3, int param_4);
参数:
* handle:PerfServiceNative_userRegScn注册的handle。
* cmd:命令
* param_1, param_2, param_3, param_4:根据命令不同的参数
命令请参见下面的常量:
public static final int CMD_SET_CPU_CORE_MIN = 0;public static final int CMD_SET_CPU_CORE_MAX = 1;public static final int CMD_SET_CPU_CORE_BIG_LITTLE_MIN = 2;public static final int CMD_SET_CPU_CORE_BIG_LITTLE_MAX = 3;public static final int CMD_SET_CPU_FREQ_MIN = 4;public static final int CMD_SET_CPU_FREQ_MAX = 5;public static final int CMD_SET_CPU_FREQ_BIG_LITTLE_MIN = 6;public static final int CMD_SET_CPU_FREQ_BIG_LITTLE_MAX = 7;public static final int CMD_SET_GPU_FREQ_MIN = 8;public static final int CMD_SET_GPU_FREQ_MAX = 9;public static final int CMD_SET_MEM_FREQ_MIN = 10;public static final int CMD_SET_MEM_FREQ_MAX = 11;public static final int CMD_SET_SCREEN_OFF_STATE = 12;public static final int CMD_SET_CPUFREQ_HISPEED_FREQ = 13;public static final int CMD_SET_CPUFREQ_MIN_SAMPLE_TIME = 14;public static final int CMD_SET_CPUFREQ_ABOVE_HISPEED_DELAY = 15;public static final int CMD_SET_VCORE = 16;
- CMD_SET_CPU_CORE_MIN:设置最少核数.参数1个 - param_1:核数
- CMD_SET_CPU_CORE_MAX:设置最大核数.参数1个 - param_1:核数
- CMD_SET_CPU_CORE_BIG_LITTLE_MIN:设置最少大小核数.参数2个 - param_1:大核数,param_2:小核数
- CMD_SET_CPU_CORE_BIG_LITTLE_MAX:设置最大大小核数.参数2个 - param_1:大核数,param_2:小核数
- CMD_SET_CPU_FREQ_MIN:设置最低频率.参数1个 - param_1:频率
- CMD_SET_CPU_FREQ_MAX:设置最高频率.参数1个 - param_1:频率
- CMD_SET_CPU_FREQ_BIG_LITTLE_MIN:设置最低大小核数.参数2个 - param_1:大核频率,param_2:小核频率
- CMD_SET_CPU_FREQ_BIG_LITTLE_MAX:设置最高大小核数.参数2个 - param_1:大核频率,param_2:小核频率
- CMD_SET_GPU_FREQ_MIN:设置GPU最低频率级别,参数1个 - param_1:频率级别
- CMD_SET_GPU_FREQ_MAX:不支持
- CMD_SET_MEM_FREQ_MIN:不支持
- CMD_SET_MEM_FREQ_MAX:不支持
- CMD_SET_VCORE:设置图形模式,参数1个:DRAM模式:0-默认模式,1-低功耗模式,2-还是默认模式,3-高性能模式
- CMD_SET_SCREEN_OFF_STATE:设置关屏模式,一个参数,模式值。0-关屏无效,1-关屏有效,2-关屏暂停,打开恢复
- CMD_SET_CPUFREQ_HISPEED_FREQ:设置高速频率,一个参数。
- CMD_SET_CPUFREQ_MIN_SAMPLE_TIME:设置最小采样值,一个参数。
- CMD_SET_CPUFREQ_ABOVE_HISPEED_DELAY:设置above speed hispeed,一个参数。
Java调用例
WebView中的应用例
例:
public void loadData(String data, String mimeType, String encoding) { checkThread(); if (TRACE) Log.d(LOGTAG, "loadData"); /// M:PerfBoost include @{ if (sFirstLoadData) { int maxFreq = 0; try { String freqFile = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"; RandomAccessFile reader = new RandomAccessFile(freqFile, "r"); String stringMaxFreq = reader.readLine(); reader.close(); maxFreq = Integer.parseInt(stringMaxFreq); } catch (IOException | NumberFormatException e) { e.printStackTrace(); } if (maxFreq != 0) { sPerfService = new PerfServiceWrapper(null); if (sPerfService != null) { int minCPU = 2; if (maxFreq < 1100000) minCPU = 4; sPerfHandle = sPerfService.userReg(minCPU, maxFreq); if (sPerfHandle != -1) { sPerfService.userEnableTimeoutMs(sPerfHandle, 500); Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { sPerfService.userUnreg(sPerfHandle); } }, 600); } } } sFirstLoadData = false; } /// @} mProvider.loadData(data, mimeType, encoding); }
AmS和WmS中的应用例
下面是/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java中定义的perfBoost的两个方法,一个是perfBoostResume,另一个是perfBoostPause.
这个就是下节我们要介绍的SCN_APP_SWITCH场景。
private void perfBoostResume() { if (mPerfService == null) { mPerfService = new PerfServiceWrapper(null); } if (mPerfService != null) { Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "amPerfBoost", 0); if (DEBUG_PERFSRV) { Slog.d(TAG, "boostEnableTimeoutMs(" + IPerfServiceWrapper.SCN_APP_SWITCH + ") cross app"); } mPerfService.boostEnableTimeoutMs(IPerfServiceWrapper.SCN_APP_SWITCH, BOOST_ENABLE_TIMEOUT); } else { Slog.e(TAG, "PerfService is not ready!"); } } public void perfBoostPause() { if (mPerfService == null) { mPerfService = new PerfServiceWrapper(null); } if (mPerfService != null) { if (DEBUG_PERFSRV) { Slog.d(TAG, "boostDisable(" + IPerfServiceWrapper.SCN_APP_SWITCH + ") cross app"); } mPerfService.boostDisable(IPerfServiceWrapper.SCN_APP_SWITCH); Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "amPerfBoost", 0); } else { Slog.e(TAG, "perfBoostPause, PerfService is not ready!"); } }
我们再看一个
if (!mIsPerfBoostEnable) { if (mPerfService == null) { mPerfService = new PerfServiceWrapper(null); } mPerfService.boostEnable(IPerfServiceWrapper.SCN_APP_ROTATE); mIsPerfBoostEnable = true; }
MTK预定义的一些场景
MediaTek预定义了这么多API,当然它自己也会有自己的预定义场景,这些场景就不需要再定义了。
libperfservice.so中预定义的场景
但是,这个值肯定不是在所有平台上都是最优的值啊,所以MTK也提供了客户定制化的机制。
定制预定义场景
定义于/vendor/mediatek/proprietary/hardware/perfservice/mt[xxxx]/scn_tbl/perfservscntbl.txt中。
我们以MT6735为例,来看一看具体的内容,定义于/vendor/mediatek/proprietary/hardware/perfservice/mt6735/scn_tbl/perfservscntbl.txt中。
CMD_SET_CPU_CORE, SCN_APP_TOUCH, 3CMD_SET_CPU_FREQ, SCN_APP_TOUCH, 819000CMD_SET_CPU_CORE, SCN_SW_FRAME_UPDATE, 3CMD_SET_CPU_FREQ, SCN_SW_FRAME_UPDATE, 819000CMD_SET_CPU_CORE, SCN_APP_SWITCH, 4CMD_SET_CPU_FREQ, SCN_APP_SWITCH, 1300000CMD_SET_CPU_UP_THRESHOLD, SCN_SW_FRAME_UPDATE, 80CMD_SET_CPU_DOWN_THRESHOLD, SCN_SW_FRAME_UPDATE, 65CMD_SET_CPU_CORE, SCN_APP_LAUNCH, 4CMD_SET_CPU_FREQ, SCN_APP_LAUNCH, 1300000
白名单
定义于:/vendor/mediatek/proprietary/hardware/perfservice/mt[xxxx]/app_list/perfservapplist.txt
格式:包名 核数
例:
com.imangi.templerun2 3
- 在MTK芯片上如何控制CPU的核数和频率-MTK PerfService
- 在MTK芯片上如何控制CPU的核心数和频率--MTK PerfService
- mtk-[FAQ20206]如何使用adb command来设置cpu频率 和核数
- [FAQ04205][FAQ04204][Power] mtk android某个核的 频率和控制在某个频率
- MTK PerfService (2) - PerfService的落地
- MTK PerfService(2)--PerfService的落地
- MTK平台CPU/GPU动态调频的实现之PerfService的源码分析
- 在MTK上实现数独小游戏
- MTK芯片
- MTK芯片
- 如何在MTK上使用RVCT
- MTK的智能芯片MT6516
- 如何在mtk andorid6.0上添加一个I2C驱动(这里是添加一个FM 芯片驱动)
- MTK 上的socket
- 如何在kernel中得到cpu的电压和频率
- MTK芯片系列手机的维修宝典
- MTK芯片系列手机的维修宝典
- android如何修改手机连接电脑显示在电脑上的名字(MTK)
- protobuf之c基础
- 【C/C++】计时函数比较
- Scrapy与Twisted
- c++快速简易入门教程_010回调函数
- android imageView 图片显示方式属性
- 在MTK芯片上如何控制CPU的核数和频率-MTK PerfService
- com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process
- GridView网格视图简单介绍
- c++快速简易入门教程_011内联函数
- 二、runtime之类和对象(二)
- 反射机制
- LeetCode - 82. Remove Duplicates from Sorted List II
- 【UI控件总结】【UIScrollView】深入理解篇UIScrollerView
- 摄像头权限被拒绝导致程序崩溃的问题(6.0以下版本)