本文對Android裝置CPU的狀態檢視方法和鎖頻(lock frequency)方法進行詳細介紹。這有什麼用?作為測試工程師,你值得了解。
CPU頻率
首先說下CPU的頻率。我們都知道,CPU的工作頻率越高,運算就越快,但能耗也更高。然而很多時候,裝置並不需要那麼高的計算效能,這個時候,我們就希望能降低CPU的工作頻率,追求較低的能耗,以此實現更長的待機時間。
基於此需求,當前電子裝置的CPU都會存在多個工作頻率,並能根據實際場景進行CPU頻率的自動切換,以此達到平衡計算效能與能耗的目的。
鎖頻的用途
那麼為什麼需要鎖頻呢?
對於普通使用者來說,可能對這些場景比較熟悉:
- 在家用膝上型電腦玩遊戲的時候,電腦連著電源,不在乎能耗,只想要儘可能高的效能,這個時候就選擇高效能模式,即保持CPU在最高頻率工作。
- 旅行途中使用膝上型電腦,靠電池供電,希望電腦能待機儘可能久,這時就選擇省電模式,即CPU保持在最低頻率執行。
作為一名測試工程師,我們在進行軟體測試的時候,為了讓測試結果真實反映軟體本身的效率,從控制變數法的角度,我們希望測試結果儘量不受到硬體本身的影響。這個時候,我們就可以嘗試對裝置的CPU進行鎖頻,即保證在測試的過程中,硬體裝置的CPU執行在一個恆定的頻率。
說到這裡先埋個伏筆,在chromium官方測試庫中,部分測試場景在初始化測試環境時,就會將裝置所有CPU的頻率調到最高狀態,後續我會單獨以一篇部落格的形式對那部分的原始碼進行分析。對於等不及的朋友,可以先去看下原始碼,原始碼路徑為pylib/perf/PerfControl.SetHighPerfMode
。
檢視CPU狀態資訊
在修改CPU的狀態之前,我們需要先檢視CPU的屬性和狀態資訊,這樣才能有針對性地進行正確的設定。
對於CPU的狀態,我們通常會關注兩類資訊,一是整體層面的,即CPU執行的核數;二是細節層面的,即各個CPU的工作狀態,包括所處工作模式、頻率大小等。
在Android系統中,CPU相關的資訊儲存在/sys/devices/system/cpu
目錄的檔案中,我們可以通過讀取該目錄下的特定檔案獲得當前裝置的CPU狀態資訊,也可以通過對該目錄下的特定檔案進行寫值,實現對CPU頻率等狀態資訊的更改。
本文以Nexus 5
(系統版本5.1.1)為例,後面的例子均以該裝置為例。不同的機型和Android系統版本可能會存在一些差異,請知悉。
在/sys/devices/system/cpu
目錄中,檔案結構如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
shell@hammerhead:/sys/devices/system/cpu $ ll drwxr-xr-x root root 2016-01-20 01:36 cpu0 drwxr-xr-x root root 2016-01-20 21:06 cpu1 drwxr-xr-x root root 2016-01-20 21:07 cpu2 drwxr-xr-x root root 2016-01-20 21:07 cpu3 -rw------- root root 4096 1970-01-17 10:27 cpuctl drwxr-xr-x root root 1970-01-17 10:27 cpufreq drwxr-xr-x root root 1970-01-17 10:27 cpuidle -r--r--r-- root root 4096 1970-01-17 10:27 kernel_max -r--r--r-- root root 4096 1970-01-17 10:27 offline -r--r--r-- root root 4096 1970-01-17 10:27 online -r--r--r-- root root 4096 1970-01-17 10:27 possible drwxr-xr-x root root 1970-01-17 10:27 power -r--r--r-- root root 4096 1970-01-17 10:27 present -rw-r--r-- root root 4096 1970-01-17 10:27 uevent |
1、view overall cpu info
在possible
檔案中,儲存的是當前裝置可用的CPU,顯示形式以數字的形式。例如0-3
代表的就是當前裝置總共有4個核,編號分別為0,1,2,3。
1 2 |
shell@hammerhead:/sys/devices/system/cpu $ cat possible 0-3 |
在online
檔案中,儲存的是當前裝置正在執行的CPU。因為有時候裝置不需要很高的效能,就可以將部分CPU關閉。不過需要注意的是,不管什麼時候,CPU0
始終都會處於執行狀態。online
檔案的儲存格式與possible
類似,如果只有部分CPU執行,且CPU編號不連續的時候,會以逗號進行隔開;例如,0,2
表示當前CPU0和CPU2處於執行狀態。
1 2 |
shell@hammerhead:/sys/devices/system/cpu $ cat online 0,2 |
對應的,offline
檔案標示的是當前裝置處於關閉狀態的CPU,這和online
作為互補,並集剛好就是裝置的所有CPU,即possible
檔案中的內容。
1 2 |
shell@hammerhead:/sys/devices/system/cpu $ cat offline 1,3 |
2、view specified cpu info
接下來,我們要獲取到特定CPU的資訊,就需要進入到對應的資料夾,例如,cpu0/
對應的就是CPU0的資訊。
在/sys/devices/system/cpu/cpu0
目錄中,檔案結構如下所示。
1 2 3 4 5 6 7 8 9 10 |
shell@hammerhead:/sys/devices/system/cpu $ ll cpu0 drwxr-xr-x root root 2016-01-20 01:37 cpufreq drwxr-xr-x root root 1970-01-17 10:27 cpuidle -r-------- root root 4096 1970-01-17 10:27 crash_notes -rw-r--r-- root root 4096 2016-01-20 01:36 online drwxr-xr-x root root 1970-01-17 10:27 power drwxr-xr-x root root 1970-01-17 10:27 rq-stats lrwxrwxrwx root root 1970-01-17 10:27 subsystem drwxr-xr-x root root 1970-01-17 10:27 topology -rw-r--r-- root root 4096 1970-01-17 10:27 uevent |
其中,online
檔案的內容表示當前CPU是否處於執行狀態,若處於執行狀態,則內容為1,否則為0;這個和上面講到的/sys/devices/system/cpu/online
能進行對應。
1 2 |
shell@hammerhead:/sys/devices/system/cpu $ cat cpu0/online 1 |
在cpu0/cpufreq/
目錄下,儲存的就是與CPU0的頻率相關的資訊,檔案結構如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
shell@hammerhead:/sys/devices/system/cpu $ ll cpu0/cpufreq/ -rw-r--r-- root root 4096 2016-01-20 01:57 UV_mV_table -r--r--r-- root root 4096 2016-01-20 01:57 affected_cpus -r--r--r-- root root 4096 2016-01-20 01:57 cpu_utilization -r-------- root root 4096 2016-01-20 01:57 cpuinfo_cur_freq -r--r--r-- root root 4096 2016-01-20 02:00 cpuinfo_max_freq -r--r--r-- root root 4096 2016-01-20 01:39 cpuinfo_min_freq -r--r--r-- root root 4096 2016-01-20 01:57 cpuinfo_transition_latency -r--r--r-- root root 4096 2016-01-20 01:57 related_cpus -r--r--r-- root root 4096 2016-01-20 01:39 scaling_available_frequencies -r--r--r-- root root 4096 2016-01-20 01:57 scaling_available_governors -r--r--r-- root root 4096 2016-01-20 01:50 scaling_cur_freq -r--r--r-- root root 4096 2016-01-20 01:57 scaling_driver -rw-r--r-- root root 4096 2016-01-20 01:50 scaling_governor -rw-r--r-- root root 4096 2016-01-20 08:29 scaling_max_freq -rw-r--r-- root root 4096 2016-01-20 08:29 scaling_min_freq -rw-r--r-- root root 4096 2016-01-20 02:52 scaling_setspeed |
在這個目錄中,我們需要關注的檔案比較多。
首先是scaling_available_governors
和scaling_governor
。這裡的governor
大家可以理解為CPU的工作模式,scaling_available_governors
中儲存了當前CPU支援的所有工作模式,而scaling_governor
儲存的是CPU當前所處的工作模式。
1 2 3 4 5 |
shell@hammerhead:/sys/devices/system/cpu $ cat cpu0/cpufreq/scaling_available_governors impulse dancedance smartmax interactive conservative ondemand userspace powersave Lionheart bioshock performance shell@hammerhead:/sys/devices/system/cpu $ cat cpu0/cpufreq/scaling_governor performance |
可以看到,Nexus 5
支援非常多的工作模式,這裡只對幾個常見的模式進行簡單說明。
- performance:最高效能模式,即使系統負載非常低,cpu也在最高頻率下執行。
- powersave:省電模式,與performance模式相反,cpu始終在最低頻率下執行。
- ondemand:CPU頻率跟隨系統負載進行變化。
- userspace:可以簡單理解為自定義模式,在該模式下可以對頻率進行設定。
對於各種模式對應的含義和策略,在此不進行展開,大家有興趣的可以自行搜尋。
然後是CPU的工作頻率範圍,對應的檔案有cpuinfo_max_freq
、cpuinfo_min_freq
、scaling_max_freq
、scaling_min_freq
。
以cpuinfo_
為字首的表示CPU硬體支援的頻率範圍,反映的是CPU自身的特性,與CPU的工作模式無關。而以scaling_
為字首的表示CPU在當前工作模式下的頻率範圍。
那麼,當前CPU工作的頻率是多少,我們要怎麼檢視呢?
檢視cpuinfo_cur_freq
或scaling_cur_freq
即可。cpuinfo_cur_freq
代表通過硬體實際上讀到的頻率值,而scaling_cur_freq
則是軟體當前的設定值,多數情況下這兩個值是一致的,但是也有可能因為硬體的原因,有微小的差異。
1 2 3 4 |
root@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq # cat cpuinfo_cur_freq 1574400 root@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq # cat scaling_cur_freq 1574400 |
更改CPU狀態資訊
最後回到我們本文的主題,如何對CPU的頻率進行設定呢?
這也和CPU資訊檢視對應,分為對CPU整體執行情況的設定,和對特定CPU工作模式的設定。
在此,有兩點需要特別進行說明。
首先,對於高通的CPU,存在一個系統服務,叫作mpdecision service
。當這個系統服務處於執行狀態時,我們無法對CPU的狀態資訊進行更改。因此,如果我們要更改高通CPU的工作模式,第一步要做的就是終止mpdecision
系統服務。
操作起來也很簡單,在Android shell裡面執行如下命令即可。
1 |
stop mpdecision |
第二點需要注意的是,如果我們想要實現對特定CPU的工作狀態進行設定,就必須將scaling_governor
設定為userspace
,只有這樣,我們才能對scaling_setspeed
進行設定。
1 2 3 4 5 6 |
root@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq # cat scaling_setspeed root@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq # echo userspace > scaling_governor root@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq # cat scaling_setspeed 1574400 |
1、set overall cpu info
從巨集觀層面,我們可以對CPU執行的核數進行設定,即可實現對特定CPU的開啟和關閉。當然,我們在前面已經說過,CPU0始終會處於執行狀態,因此我們無法將CPU0進行關閉。
設定的方式很簡單,就是往/sys/devices/system/cpu/cpu[i]/online
檔案中寫值即可,寫1時開啟指定CPU,寫0時關閉指定CPU。
1 2 3 4 |
# turn off cpu1 root@hammerhead:/sys/devices/system/cpu/cpu1 # echo 0 > online root@hammerhead:/sys/devices/system/cpu/cpu1 # cat online 0 |
2、set specified cpu info
在對特定CPU的頻率進行設定前,我們需要知道的是,CPU並不能工作在任意頻率下,我們只能將CPU的頻率設定為它支援的數值。
通過檢視scaling_available_frequencies
,我們可以獲得當前CPU支援的頻率值。
1 2 |
root@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq # cat scaling_available_frequencies 300000 422400 652800 729600 883200 960000 1036800 1190400 1267200 1497600 1574400 1728000 1958400 2265600 |
接下來,我們就可以對CPU的工作頻率進行設定了。
如何進行設定呢?剛開始的時候,我覺得將特定的頻率值寫入scaling_setspeed
或scaling_cur_freq
就可以了,通過Google搜尋得到的方法中也是這種方式。
但經過嘗試,發現並不可行。為什麼會這樣?我也還沒有找到答案,希望知道原因的朋友能告訴我。
最後經過嘗試,發現通過同時將scaling_max_freq
和scaling_min_freq
設定為目標頻率值,就可以成功地對CPU頻率完成設定。
1 2 3 4 5 6 7 8 9 10 11 |
# before setting shell@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq $ cat scaling_cur_freq 1574400 # setting shell@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq $ echo 1728000 > scaling_min_freq shell@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq $ echo 1728000 > scaling_max_freq # after setting shell@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq $ cat scaling_cur_freq 1728000 |