天天看點

Android程序線程排程nice等優先級讨論 程序排程nice值 線程排程API 啟發優化政策:

程序排程nice值

  • 關于nice的基本概念:

Linux中,使用nice value來設定一個程序的優先級,android 也會用這一套機制。系統任務排程器根據nice值合理安排排程。

>nice的取值範圍為-20到19。
>通常情況下,nice的預設值為0。視具體作業系統而定。
>nice的值越大,程序的優先級就越低,獲得CPU調用的機會越少,nice值越小,程序的優先級則越高,獲得CPU調用的機會越多。
>一個nice值為-20的程序優先級最高,nice值為19的程序優先級最低。
>父程序fork出來的子程序nice值與父程序相同。父程序renice,子程序nice值不會随之改變。
           

這個并不是最終的優先級, 真正的程序優先級是要經過一定的計算, 也就是說nice會影響靜态優先級。 看代碼:/kernel/kernel/sched/sched.h (Android 7.0)

/*
* Convert user-nice values [ -20 ... 0 ... 19 ]
* to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
* and back.
*/
#define NICE_TO_PRIO(nice) (MAX_RT_PRIO + (nice) + 20)
#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20)
           

其中 MAX_RT_PRIO = 100 。

android中nice的用法:

$ nice
usage: nice [-n PRIORITY] command [args...]
Run a command line at an increased or decreased scheduling priority.
Higher numbers make a program yield more CPU time, from -20 (highest
priority) to 19 (lowest). By default processes inherit their parent's
niceness (usually 0). By default this command adds 10 to the parent's
priority. Only root can set a negative niceness level.
nice: Needs 1 argument
           
  • renice使用:

對于一個新的程序我們可以按照下面的代碼為一個程序設定nice值。

$ renice
usage: renice [-gpu] -n increment ID ...
renice: Needs 1 argument
           

不能root不能使用, 通常我們調試性能會在user 版本上調試, 不能root,我們刷能root的boot image進行驗證行的調試, 并不能作為重要正式結果。

線程排程API

我們在app層和framework層是有機制與nice機制相對應的, nice是對程序的, 以下是可對線程的, 效果異曲同工。

分為Java API 和 Android API

  • Java API:

Java為Thread提供了三個級别的設定。

MAX_PRIORITY,相當于android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY,值為10。
MIN_PRIORITY,相當于android.os.Process.THREAD_PRIORITY_LOWEST,值為0。
NORM_PRIORITY,相當于android.os.Process.THREAD_PRIORITY_DEFAULT,值為5。
           

使用setPriority我們可以為某個線程設定優先級,使用getPriority可以獲得某個線程的優先級。

在Android系統中,不建議使用Java原生的API,因為Android提供的API劃分的級别更多,更适合在Android系統中進行設定細緻的優先級。

  • Android API:
THREAD_PRIORITY_DEFAULT,預設的線程優先級,值為0。
THREAD_PRIORITY_LOWEST,最低的線程級别,值為19。
THREAD_PRIORITY_BACKGROUND 背景線程建議設定這個優先級,值為10。
THREAD_PRIORITY_FOREGROUND 使用者正在互動的UI線程,代碼中無法設定該優先級,系統會按照情況調整到該優先級,值為-2。
THREAD_PRIORITY_DISPLAY 也是與UI互動相關的優先級界别,但是要比THREAD_PRIORITY_FOREGROUND優先,代碼中無法設定,由系統按照情況調整,值為-4。
THREAD_PRIORITY_URGENT_DISPLAY 顯示線程的最進階别,用來處理繪制畫面和檢索輸入事件,代碼中無法設定成該優先級。值為-8。
THREAD_PRIORITY_AUDIO 聲音線程的标準級别,代碼中無法設定為該優先級,值為 -16。
THREAD_PRIORITY_URGENT_AUDIO 聲音線程的最進階别,優先程度較THREAD_PRIORITY_AUDIO要高。代碼中無法設定為該優先級。值為-19。
THREAD_PRIORITY_MORE_FAVORABLE 相對THREAD_PRIORITY_DEFAULT稍微優先,值為-1。
THREAD_PRIORITY_LESS_FAVORABLE 相對THREAD_PRIORITY_DEFAULT稍微落後一些,值為1。
           

使用Android API為線程設定優先級也很簡單,隻需要線上程執行時調用android.os.Process.setThreadPriority方法即可。這種線上程運作時進行修改優先級,效果類似renice。

  • Java API 與Android API的關系:

Android API的線程優先級和Java原生API的優先級是相對獨立的,比如使用android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)後,使用Java原生API,Thread.getPriority()得到的值不會改變。

啟發優化政策:

在framework層進行對所有程序的監控和行為分析(核心算法實作暫不開源 TODO),給程序進行分類,差別進行類似于再renice處理。讓IO消費型程序再提高優先級, 響應使用者操作的線程得到較高優先級, CPU消費型程序再降低優先級。

  • 風險:

此feature打破原有打分機制, 可能對程序類型評估是準确,導緻不可預知的搶占不到資源。

歡迎大家讨論

繼續閱讀