在MTK芯片上如何控制CPU的核数和频率-MTK PerfService
在MTK芯片上如何控制CPU的核數(shù)和頻率-MTK PerfService
一句話:PerfService就是用來調(diào)整CPU/GPU資源的。對于老的API,可以更簡單地講就是調(diào)CPU核數(shù)和CPU頻率的。
PerfService簡介
kernel中實(shí)現(xiàn)了兩個(gè)driver,一個(gè)負(fù)責(zé)控制開關(guān)CPU的核數(shù),叫做hot-plug驅(qū)動,另一個(gè)負(fù)責(zé)調(diào)整CPU的頻率,叫做DVFS驅(qū)動。
kernel中的driver會根據(jù)系統(tǒng)的負(fù)載情況下,自動調(diào)整使用幾個(gè)CPU和調(diào)整CPU頻率。如果負(fù)載高了,提高頻率,或者多開幾個(gè)核,或者開大核。如果負(fù)載降下去了,就可以關(guān)大核,關(guān)核,降頻。
雖然現(xiàn)在的自動調(diào)頻和調(diào)核的策略已經(jīng)定義了很多,也在不斷地完善,但是有兩個(gè)問題:一是總有覆蓋不到的情況,或者干脆就是互相矛盾的需求導(dǎo)致策略沖突。二是自動調(diào)度都是后知后覺的,只有發(fā)現(xiàn)負(fù)載上來了或者降下去了,才來做負(fù)載調(diào)節(jié),需要一定的時(shí)間。這樣,要么是效率不夠,要么是功耗無謂地消耗掉。
PerfService就是一個(gè)在用戶空間來主動調(diào)節(jié)系統(tǒng)能力的服務(wù)。
C/C++調(diào)用PerfService
步驟
- 動態(tài)加載libperfservicenative.so
- 注冊用戶場景PerfServiceNative_userReg/PerfServiceNative_userRegBigLittle/PerfServiceNative_userRegScn
- 激活用戶場景PerfServiceNative_userEnable
- 執(zhí)行用戶場景
- 反激活用戶場景PerfServiceNative_userDisable
- 退出進(jìn)程之前反注冊PerfServiceNative_userUnreg/PerfServiceNative_userUnregScn
老API的步驟
老API只能對CPU做調(diào)度,但是好處是可以直接指定開幾個(gè)核,頻率調(diào)到多少,還可以控制開大核還是小核。
- PerfServiceNative_userReg可以指定幾個(gè)核和多高的頻率
- PerfServiceNative_userRegBigLittle還可以用來指定調(diào)度大小核
- PerfServiceNative_userEnable用來激活上面注冊的場景,PerfServiceNative_userEnableTimeout可以指定激活的超時(shí)時(shí)間
- PerfServiceNative_userDisable用來反激活
- PerfServiceNative_userUnreg反注冊
新API的步驟
新的API也可以調(diào)節(jié)GPU,但是采用的方式要復(fù)雜一些,就不再像老API一樣直接指定核和頻率了,需要定義配置
- PerfServiceNative_userRegScn:沒有參數(shù),直接注冊就好
- PerfServiceNative_userRegScnConfig:用這個(gè)函數(shù)去真正指定配置
- PerfServiceNative_userEnable/PerfServiceNative_userEnableTimeout:跟老API沒有區(qū)別
- PerfServiceNative_userDisable:還是老的API
- PerfServiceNative_userUnregScn:反注冊
老API開發(fā)指南
指定核和頻率PerfServiceNative_userReg
定義一個(gè)需要scn_core個(gè)核,scn_freq頻率運(yùn)行的任務(wù)
原型:
int PerfServiceNative_userReg(int scn_core, int scn_freq);定義于:/mediatek/proprietary/hardware/perfservice/perfservicenative/PerfServiceNative.h
參數(shù):
* scn_core:開多少個(gè)核
* scn_freq:頻率調(diào)整到多少。如果只是希望多開幾個(gè)核或者少開幾個(gè)核,并不關(guān)注頻率的話,可以置成0.
返回值:
* -1:失敗
* other:handler,用于后續(xù)的操作
注冊指定大核小核PerfServiceNative_userRegBigLittle
定義一個(gè)需要scn_core個(gè)核,scn_freq頻率運(yùn)行的任務(wù)
原型:
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
參數(shù):
* scn_core_big:開多少個(gè)核
* scn_freq_big:頻率調(diào)整到多少
* scn_core_little:開多少個(gè)核
* scn_freq_little:頻率調(diào)整到多少
返回值:
* -1:失敗
* other:handler
反注冊
在退出進(jìn)程之前需要進(jìn)行反注冊
原型:
void PerfServiceNative_userUnreg(int handle);激活和反激活
注冊了之后也不是一直用啊,用的時(shí)候再打開吧,使用PerfServiceNative_userEnable。如果一旦憂心有可能出exception之類的流程不能保證走到PerfServiceNative_userDisable的話,也可以加個(gè)超時(shí),調(diào)用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);參數(shù):
* handle: 注冊成功后返回的那個(gè)
* timeout: PerfServiceNative_userEnableTimeout是以秒為單位的超時(shí)時(shí)間,PerfServiceNative_userEnableTimeoutMs則以毫秒為單位。
新API開發(fā)指南
獲取系統(tǒng)能力
int PerfServiceNative_userGetCapability(int cmd);參數(shù):
* cmd: 請參見下面的枚舉值:
- 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:獲取內(nèi)存頻率級別
注冊
因?yàn)樾碌腁PI還需要指定配置,所以注冊獲取handle就不需要參數(shù)了。
原型:
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);參數(shù):
* handle:PerfServiceNative_userRegScn注冊的handle。
* cmd:命令
* param_1, param_2, param_3, param_4:根據(jù)命令不同的參數(shù)
命令請參見下面的枚舉:
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:設(shè)置最少核數(shù).參數(shù)1個(gè) - param_1:核數(shù)
- CMD_SET_CPU_CORE_MAX:設(shè)置最大核數(shù).參數(shù)1個(gè) - param_1:核數(shù)
- CMD_SET_CPU_CORE_BIG_LITTLE_MIN:設(shè)置最少大小核數(shù).參數(shù)2個(gè) - param_1:大核數(shù),param_2:小核數(shù)
- CMD_SET_CPU_CORE_BIG_LITTLE_MAX:設(shè)置最大大小核數(shù).參數(shù)2個(gè) - param_1:大核數(shù),param_2:小核數(shù)
- CMD_SET_CPU_FREQ_MIN:設(shè)置最低頻率.參數(shù)1個(gè) - param_1:頻率
- CMD_SET_CPU_FREQ_MAX:設(shè)置最高頻率.參數(shù)1個(gè) - param_1:頻率
- CMD_SET_CPU_FREQ_BIG_LITTLE_MIN:設(shè)置最低大小核數(shù).參數(shù)2個(gè) - param_1:大核頻率,param_2:小核頻率
- CMD_SET_CPU_FREQ_BIG_LITTLE_MAX:設(shè)置最高大小核數(shù).參數(shù)2個(gè) - param_1:大核頻率,param_2:小核頻率
- CMD_SET_GPU_FREQ_MIN:設(shè)置GPU最低頻率級別,參數(shù)1個(gè) - param_1:頻率級別
- CMD_SET_GPU_FREQ_MAX:不支持
- CMD_SET_MEM_FREQ_MIN:不支持
- CMD_SET_MEM_FREQ_MAX:不支持
- CMD_SET_VCORE:設(shè)置圖形模式,參數(shù)1個(gè):DRAM模式:0-默認(rèn)模式,1-低功耗模式,2-還是默認(rèn)模式,3-高性能模式
- CMD_SET_SCREEN_OFF_STATE:設(shè)置關(guān)屏模式,一個(gè)參數(shù),模式值。0-關(guān)屏無效,1-關(guān)屏有效,2-關(guān)屏?xí)和?#xff0c;打開恢復(fù)
- CMD_SET_CPUFREQ_HISPEED_FREQ:設(shè)置高速頻率,一個(gè)參數(shù)。
- CMD_SET_CPUFREQ_MIN_SAMPLE_TIME:設(shè)置最小采樣值,一個(gè)參數(shù)。
- CMD_SET_CPUFREQ_ABOVE_HISPEED_DELAY:設(shè)置above speed hispeed,一個(gè)參數(shù)。
開關(guān)屏的參數(shù),請使用下面的枚舉值:
enum {SCREEN_OFF_DISABLE = 0,SCREEN_OFF_ENABLE = 1,SCREEN_OFF_WAIT_RESTORE = 2, };Java調(diào)用PerfService
步驟
- import IPerfServiceWrapper和PerfServiceWrapper
- 注冊用戶場景IPerfServiceWrapper.userReg
- 激活用戶場景IPerfServiceWrapper.userEnable
- 執(zhí)行用戶場景
- 反激活用戶場景IPerfServiceWrapper.userDisable
- 反注冊用戶場景IPerfServiceWrapper.userUnreg
IPerfServiceWrapper定義于
/frameworks/base/core/java/com/mediatek/perfservice/IPerfServiceWrapper.java
老API的步驟
老API只能對CPU做調(diào)度,但是好處是可以直接指定開幾個(gè)核,頻率調(diào)到多少,還可以控制開大核還是小核。
- IPerfServiceWrapper.userReg可以指定幾個(gè)核和多高的頻率
- IPerfServiceWrapper.userRegBigLittle還可以用來指定調(diào)度大小核
- IPerfServiceWrapper.userEnable用來激活上面注冊的場景,IPerfServiceWrapper.userEnableTimeout可以指定激活的超時(shí)時(shí)間
- IPerfServiceWrapper.userDisable用來反激活
- IPerfServiceWrapper.userUnreg反注冊
新API的步驟
新的API也可以調(diào)節(jié)GPU,但是采用的方式要復(fù)雜一些,就不再像老API一樣直接指定核和頻率了,需要定義配置
- IPerfServiceWrapper.userRegScn:沒有參數(shù),直接注冊就好
- IPerfServiceWrapper.userRegScnConfig:用這個(gè)函數(shù)去真正指定配置
- IPerfServiceWrapper.userEnable/IPerfServiceWrapper.userEnableTimeout:跟老API沒有區(qū)別
- IPerfServiceWrapper.userDisable:還是老的API
- IPerfServiceWrapper.userUnregScn:反注冊
老API開發(fā)指南
指定核和頻率PerfServiceNative_userReg
定義一個(gè)需要scn_core個(gè)核,scn_freq頻率運(yùn)行的任務(wù)
原型:
public int userReg(int scn_core, int scn_freq);參數(shù):
* scn_core:開多少個(gè)核
* scn_freq:頻率調(diào)整到多少。如果只是希望多開幾個(gè)核或者少開幾個(gè)核,并不關(guān)注頻率的話,可以置成0.
返回值:
* -1:失敗
* other:handler,用于后續(xù)的操作
注冊指定大核小核PerfServiceNative_userRegBigLittle
定義一個(gè)需要scn_core個(gè)核,scn_freq頻率運(yùn)行的任務(wù)
原型:
public int userRegBigLittle(int scn_core_big, int scn_freq_big, int scn_core_little, int scn_freq_little);參數(shù):
* scn_core_big:開多少個(gè)核
* scn_freq_big:頻率調(diào)整到多少
* scn_core_little:開多少個(gè)核
* scn_freq_little:頻率調(diào)整到多少
返回值:
* -1:失敗
* other:handler
反注冊
在退出進(jìn)程之前需要進(jìn)行反注冊
原型:
public void userUnreg(int handle);激活和反激活
注冊了之后也不是一直用啊,用的時(shí)候再打開吧,使用PerfServiceNative_userEnable。如果一旦憂心有可能出exception之類的流程不能保證走到PerfServiceNative_userDisable的話,也可以加個(gè)超時(shí),調(diào)用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);參數(shù):
* handle: 注冊成功后返回的那個(gè)
* timeout: PerfServiceNative_userEnableTimeout是以秒為單位的超時(shí)時(shí)間,PerfServiceNative_userEnableTimeoutMs則以毫秒為單位。
新API開發(fā)指南
獲取系統(tǒng)能力
public int userGetCapability(int cmd);參數(shù):
* cmd: 請參見下面的常量值:
- 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:獲取內(nèi)存頻率級別
注冊
因?yàn)樾碌腁PI還需要指定配置,所以注冊獲取handle就不需要參數(shù)了。
原型:
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);參數(shù):
* handle:PerfServiceNative_userRegScn注冊的handle。
* cmd:命令
* param_1, param_2, param_3, param_4:根據(jù)命令不同的參數(shù)
命令請參見下面的常量:
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:設(shè)置最少核數(shù).參數(shù)1個(gè) - param_1:核數(shù)
- CMD_SET_CPU_CORE_MAX:設(shè)置最大核數(shù).參數(shù)1個(gè) - param_1:核數(shù)
- CMD_SET_CPU_CORE_BIG_LITTLE_MIN:設(shè)置最少大小核數(shù).參數(shù)2個(gè) - param_1:大核數(shù),param_2:小核數(shù)
- CMD_SET_CPU_CORE_BIG_LITTLE_MAX:設(shè)置最大大小核數(shù).參數(shù)2個(gè) - param_1:大核數(shù),param_2:小核數(shù)
- CMD_SET_CPU_FREQ_MIN:設(shè)置最低頻率.參數(shù)1個(gè) - param_1:頻率
- CMD_SET_CPU_FREQ_MAX:設(shè)置最高頻率.參數(shù)1個(gè) - param_1:頻率
- CMD_SET_CPU_FREQ_BIG_LITTLE_MIN:設(shè)置最低大小核數(shù).參數(shù)2個(gè) - param_1:大核頻率,param_2:小核頻率
- CMD_SET_CPU_FREQ_BIG_LITTLE_MAX:設(shè)置最高大小核數(shù).參數(shù)2個(gè) - param_1:大核頻率,param_2:小核頻率
- CMD_SET_GPU_FREQ_MIN:設(shè)置GPU最低頻率級別,參數(shù)1個(gè) - param_1:頻率級別
- CMD_SET_GPU_FREQ_MAX:不支持
- CMD_SET_MEM_FREQ_MIN:不支持
- CMD_SET_MEM_FREQ_MAX:不支持
- CMD_SET_VCORE:設(shè)置圖形模式,參數(shù)1個(gè):DRAM模式:0-默認(rèn)模式,1-低功耗模式,2-還是默認(rèn)模式,3-高性能模式
- CMD_SET_SCREEN_OFF_STATE:設(shè)置關(guān)屏模式,一個(gè)參數(shù),模式值。0-關(guān)屏無效,1-關(guān)屏有效,2-關(guān)屏?xí)和?#xff0c;打開恢復(fù)
- CMD_SET_CPUFREQ_HISPEED_FREQ:設(shè)置高速頻率,一個(gè)參數(shù)。
- CMD_SET_CPUFREQ_MIN_SAMPLE_TIME:設(shè)置最小采樣值,一個(gè)參數(shù)。
- CMD_SET_CPUFREQ_ABOVE_HISPEED_DELAY:設(shè)置above speed hispeed,一個(gè)參數(shù)。
Java調(diào)用例
WebView中的應(yīng)用例
例:
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() {@Overridepublic void run() {sPerfService.userUnreg(sPerfHandle);}}, 600);}}}sFirstLoadData = false;}/// @}mProvider.loadData(data, mimeType, encoding);}AmS和WmS中的應(yīng)用例
下面是/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java中定義的perfBoost的兩個(gè)方法,一個(gè)是perfBoostResume,另一個(gè)是perfBoostPause.
這個(gè)就是下節(jié)我們要介紹的SCN_APP_SWITCH場景。
我們再看一個(gè)
if (!mIsPerfBoostEnable) {if (mPerfService == null) {mPerfService = new PerfServiceWrapper(null);}mPerfService.boostEnable(IPerfServiceWrapper.SCN_APP_ROTATE);mIsPerfBoostEnable = true;}MTK預(yù)定義的一些場景
MediaTek預(yù)定義了這么多API,當(dāng)然它自己也會有自己的預(yù)定義場景,這些場景就不需要再定義了。
libperfservice.so中預(yù)定義的場景
| SCN_APP_SWITCH | 2 | - | app啟動、退出 |
| SCN_APP_ROTATE | 2 | - | app rotate |
| SCN_APP_TOUCH | 2 | 169000 | touch |
但是,這個(gè)值肯定不是在所有平臺上都是最優(yōu)的值啊,所以MTK也提供了客戶定制化的機(jī)制。
定制預(yù)定義場景
定義于/vendor/mediatek/proprietary/hardware/perfservice/mt[xxxx]/scn_tbl/perfservscntbl.txt中。
我們以MT6735為例,來看一看具體的內(nèi)容,定義于/vendor/mediatek/proprietary/hardware/perfservice/mt6735/scn_tbl/perfservscntbl.txt中。
CMD_SET_CPU_CORE, SCN_APP_TOUCH, 3 CMD_SET_CPU_FREQ, SCN_APP_TOUCH, 819000 CMD_SET_CPU_CORE, SCN_SW_FRAME_UPDATE, 3 CMD_SET_CPU_FREQ, SCN_SW_FRAME_UPDATE, 819000 CMD_SET_CPU_CORE, SCN_APP_SWITCH, 4 CMD_SET_CPU_FREQ, SCN_APP_SWITCH, 1300000 CMD_SET_CPU_UP_THRESHOLD, SCN_SW_FRAME_UPDATE, 80 CMD_SET_CPU_DOWN_THRESHOLD, SCN_SW_FRAME_UPDATE, 65 CMD_SET_CPU_CORE, SCN_APP_LAUNCH, 4 CMD_SET_CPU_FREQ, SCN_APP_LAUNCH, 1300000白名單
定義于:/vendor/mediatek/proprietary/hardware/perfservice/mt[xxxx]/app_list/perfservapplist.txt
格式:包名 核數(shù)
例:
com.imangi.templerun2 3總結(jié)
以上是生活随笔為你收集整理的在MTK芯片上如何控制CPU的核数和频率-MTK PerfService的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle cpu基线,Oracle
- 下一篇: Android权限Uri.parse的详