Android系統「資源調度框架」
- 2021 年 7 月 10 日
- 筆記
- Android, performance
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一套系統服務和封裝內核介面。
重點還是這些介面使用,因為涉及到全局的性能,所以完善的測試是必要的。
四、資料
MTK平台CPU/GPU動態調頻的實現之PerfService的源碼分析