在MTK芯片上如何控制CPU的核数和频率-MTK PerfService
一句话:PerfService就是用来调整CPU/GPU资源的。对于老的API,可以更简单地讲就是调CPU核数和CPU频率的。
简介
kernel中实现了两个driver,一个负责控制开关CPU的核数,叫做hot-plug驱动,另一个负责调整CPU的频率,叫做DVFS驱动。
kernel中的driver会根据系统的负载情况下,自动调整使用几个CPU和调整CPU频率。如果负载高了,提高频率,或者多开几个核,或者开大核。如果负载降下去了,就可以关大核,关核,降频。
虽然现在的自动调频和调核的策略已经定义了很多,也在不断地完善,但是有两个问题:一是总有覆盖不到的情况,或者干脆就是互相矛盾的需求导致策略冲突。二是自动调度都是后知后觉的,只有发现负载上来了或者降下去了,才来做负载调节,需要一定的时间。这样,要么是效率不够,要么是功耗无谓地消耗掉。
PerfService就是一个在用户空间来主动调节系统能力的服务。
调用PerfService
步骤
- 动态加载libperfservicenative.so
- 注册用户场景PerfServiceNative_userReg/PerfServiceNative_userRegBigLittle/PerfServiceNative_userRegScn
- 激活用户场景PerfServiceNative_userEnable
- 执行用户场景
- 反激活用户场景PerfServiceNative_userDisable
- 退出进程之前反注册PerfServiceNative_userUnreg/PerfServiceNative_userUnregScn
API的步骤
API也可以调节GPU,但是采用的方式要复杂一些,就不再像老API一样直接指定核和频率了,需要定义配置
- PerfServiceNative_userRegScn:没有参数,直接注册就好
- PerfServiceNative_userRegScnConfig:用这个函数去真正指定配置
- PerfServiceNative_userEnable/PerfServiceNative_userEnableTimeout:跟老API没有区别
- PerfServiceNative_userDisable:还是老的API
- PerfServiceNative_userUnregScn:反注册
API开发指南
获取系统能力
1intPerfServiceNative_userGetCapability(int cmd);
参数:
* cmd: 请参见下面的枚举值:
1enum{
1CMD_GET_CPU_FREQ_LEVEL_COUNT = 0,
1CMD_GET_CPU_FREQ_LITTLE_LEVEL_COUNT = 1,
1CMD_GET_CPU_FREQ_BIG_LEVEL_COUNT =2,
1CMD_GET_GPU_FREQ_LEVEL_COUNT =3,
1CMD_GET_MEM_FREQ_LEVEL_COUNT =4,
1};
- 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就不需要参数了。
原型:
1int PerfServiceNative_userRegScn();
反注册
反注册PerfServiceNative_userRegScn注册的handle。注意,跟PerfServiceNative_userUnreg不一样啊。
1voidPerfServiceNative_userUnregScn(
int handle);
配置
原型:
1
2
3
4
5
6voidPerfServiceNative_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:根据命令不同的参数
命令请参见下面的枚举:
1enum{
1CMD_SET_CPU_CORE_MIN = 0,
1CMD_SET_CPU_CORE_MAX = 1,
1CMD_SET_CPU_CORE_BIG_LITTLE_MIN = 2,
1CMD_SET_CPU_CORE_BIG_LITTLE_MAX = 3,
1CMD_SET_CPU_FREQ_MIN = 4,
1CMD_SET_CPU_FREQ_MAX = 5,
1CMD_SET_CPU_FREQ_BIG_LITTLE_MIN = 6,
1CMD_SET_CPU_FREQ_BIG_LITTLE_MAX = 7,
1CMD_SET_GPU_FREQ_MIN =8,
1CMD_SET_GPU_FREQ_MAX = 9,
1CMD_SET_MEM_FREQ_MIN = 10,
1CMD_SET_MEM_FREQ_MAX = 11,
1CMD_SET_VCORE = 12,
1CMD_SET_SCREEN_OFF_STATE = 13,
1CMD_SET_CPUFREQ_HISPEED_FREQ = 14,
1CMD_SET_CPUFREQ_MIN_SAMPLE_TIME = 15,
1CMD_SET_CPUFREQ_ABOVE_HISPEED_DELAY = 16,
1};
- 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,一个参数。
开关屏的参数,请使用下面的枚举值:
1enum{
1SCREEN_OFF_DISABLE = 0,
1SCREEN_OFF_ENABLE = 1,
1SCREEN_OFF_WAIT_RESTORE = 2,
1};
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也可以调节GPU,但是采用的方式要复杂一些,就不再像老API一样直接指定核和频率了,需要定义配置
- IPerfServiceWrapper.userRegScn:没有参数,直接注册就好
- IPerfServiceWrapper.userRegScnConfig:用这个函数去真正指定配置
- IPerfServiceWrapper.userEnable/IPerfServiceWrapper.userEnableTimeout:跟老API没有区别
- IPerfServiceWrapper.userDisable:还是老的API
- IPerfServiceWrapper.userUnregScn:反注册
新API开发指南
获取系统能力
1publicintuserGetCapability(int cmd);
参数:
* cmd: 请参见下面的常量值:
1publicstaticfinalintCMD_GET_CPU_FREQ_LEVEL_COUNT = 0;
1publicstaticfinalintCMD_GET_CPU_FREQ_LITTLE_LEVEL_COUNT = 1;
1publicstaticfinalintCMD_GET_CPU_FREQ_BIG_LEVEL_COUNT = 2;
1publicstaticfinalintCMD_GET_GPU_FREQ_LEVEL_COUNT = 3;
1publicstaticfinalintCMD_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就不需要参数了。
原型:
1publicintuserRegScn();
反注册
反注册PerfServiceNative_userRegScn注册的handle。注意,跟PerfServiceNative_userUnreg不一样啊。
原型:
1publicvoiduserUnregScn(int handle);
配置
原型:
1
2
3
4
5
6publicvoiduserRegScnConfig(
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:根据命令不同的参数
命令请参见下面的常量:
1publicstaticfinalintCMD_SET_CPU_CORE_MIN = 0;
1publicstaticfinalintCMD_SET_CPU_CORE_MAX =1;
1publicstaticfinalintCMD_SET_CPU_CORE_BIG_LITTLE_MIN = 2;
1publicstaticfinalintCMD_SET_CPU_CORE_BIG_LITTLE_MAX =3;
1publicstaticfinalintCMD_SET_CPU_FREQ_MIN =4;
1publicstaticfinalintCMD_SET_CPU_FREQ_MAX = 5;
1publicstaticfinalintCMD_SET_CPU_FREQ_BIG_LITTLE_MIN = 6;
1publicstaticfinalintCMD_SET_CPU_FREQ_BIG_LITTLE_MAX = 7;
1publicstaticfinalintCMD_SET_GPU_FREQ_MIN =8;
1publicstaticfinalintCMD_SET_GPU_FREQ_MAX = 9;
1publicstaticfinalintCMD_SET_MEM_FREQ_MIN = 10;
1publicstaticfinalintCMD_SET_MEM_FREQ_MAX = 11;
1publicstaticfinalintCMD_SET_SCREEN_OFF_STATE = 12;
1publicstaticfinalintCMD_SET_CPUFREQ_HISPEED_FREQ =13;
1publicstaticfinalintCMD_SET_CPUFREQ_MIN_SAMPLE_TIME =14;
1publicstaticfinalintCMD_SET_CPUFREQ_ABOVE_HISPEED_DELAY = 15;
1publicstaticfinalintCMD_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中的应用例
例:
1publicvoidloadData(String data, String mimeType, String encoding)
{checkThread();
1if(TRACE) Log.d(LOGTAG, "loadData");
1/// M:PerfBoost include @{
1if(sFirstLoadData) {
1int maxFreq = 0;
1try{
1String freqFile = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
1RandomAccessFile reader = newRandomAccessFile(freqFile, "r");
1String stringMaxFreq = reader.readLine();
1reader.close();
1maxFreq = Integer.parseInt(stringMaxFreq);
1}
catch (IOException | NumberFormatException e) {
1e.printStackTrace(); }
1if(maxFreq != 0) {
1sPerfService = new PerfServiceWrapper(null);
1if(sPerfService != null)
{int minCPU = 2;
if (maxFreq <1100000)
1minCPU = 4;
1sPerfHandle = sPerfService.userReg(minCPU, maxFreq);
1if (sPerfHandle != -1)
1{
1sPerfService.userEnableTimeoutMs(sPerfHandle, 500);
1Handler handler = newHandler();
1handler.postDelayed(new Runnable()
{
1@Override
1publicvoidrun() {
1sPerfService.userUnreg(sPerfHandle);
1}
1},
600);
1}
1}
1}
1sFirstLoadData = false;
1}
1/// @}
1
1mProvider.loadData(data, mimeType, encoding);
1}
MTK预定义的一些场景
MediaTek预定义了这么多API,当然它自己也会有自己的预定义场景,这些场景就不需要再定义了。
libperfservice.so中预定义的场景
场景 | cpu核数 | cpu频率 | UI操作 |
SCN_APP_SWITCH | 2 | - | app启动、退出 |
SCN_APP_ROTATE | 2 | - | app rotate |
SCN_APP_TOUCH | 2 | 169000 | touch |
但是,这个值肯定不是在所有平台上都是最优的值啊,所以MTK也提供了客户定制化的机制。
定制预定义场景
定义于/vendor/mediatek/proprietary/hardware/perfservice/mt[xxxx]/scn_tbl/perfservscntbl.txt中。
我们以MT6735为例,来看一看具体的内容,定义于/vendor/mediatek/proprietary/hardware/perfservice/mt6735/scn_tbl/perfservscntbl.txt中。
1CMD_SET_CPU_CORE, SCN_APP_TOUCH, 3
1CMD_SET_CPU_FREQ, SCN_APP_TOUCH, 819000
1CMD_SET_CPU_CORE, SCN_SW_FRAME_UPDATE, 3
1CMD_SET_CPU_FREQ, SCN_SW_FRAME_UPDATE, 819000
1CMD_SET_CPU_CORE, SCN_APP_SWITCH, 4
1CMD_SET_CPU_FREQ, SCN_APP_SWITCH, 1300000
1CMD_SET_CPU_UP_THRESHOLD, SCN_SW_FRAME_UPDATE, 80
1CMD_SET_CPU_DOWN_THRESHOLD, SCN_SW_FRAME_UPDATE, 65
1CMD_SET_CPU_CORE, SCN_APP_LAUNCH, 4
1CMD_SET_CPU_FREQ, SCN_APP_LAUNCH, 1300000
白名单
定义于:/vendor/mediatek/proprietary/hardware/perfservice/mt[xxxx]/app_list/perfservapplist.txt
格式:包名核数
例:
1com.imangi.templerun2 3
1
2
最后
以上就是简单冷风最近收集整理的关于MTK 功耗优化(1)---MTK PerfService在MTK芯片上如何控制CPU的核数和频率-MTK PerfService的全部内容,更多相关MTK内容请搜索靠谱客的其他文章。
发表评论 取消回复