扣丁書屋

Android Systrace 基礎知識(12) - Kernel_CPU Info 解讀

本文是 Systrace 系列文章的第十二篇,主要是對 Systrace 中的 CPU 信息區域(Kernel)進行簡單介紹,簡單介紹了如何在 Systrace 中查看 Kernel 模塊輸出的 CPU 相關的信息,了解 CPU 頻率、調度、鎖頻、鎖核相關的信息

本系列的目的是通過 Systrace 這個工具,從另外一個角度來看待 Android 系統整體的運行,同時也從另外一個角度來對 Framework 進行學習。也許你看了很多講 Framework 的文章,但是總是記不住代碼,或者不清楚其運行的流程,也許從 Systrace 這個圖形化的角度,你可以理解的更深入一些。

系列文章目錄

  1. [Systrace 簡介[1]]
  2. [Systrace 基礎知識 - Systrace 預備知識[2]]
  3. [Systrace 基礎知識 - Why 60 fps ?[3]]
  4. [Systrace 基礎知識 - SystemServer 解讀[4]]
  5. [Systrace 基礎知識 - SurfaceFlinger 解讀[5]]
  6. [Systrace 基礎知識 - Input 解讀[6]]
  7. [Systrace 基礎知識 - Vsync 解讀[7]]
  8. [Systrace 基礎知識 - Vsync-App :基于 Choreographer 的渲染機制詳解[8]]
  9. [Systrace 基礎知識 - MainThread 和 RenderThread 解讀[9]]
  10. [Systrace 基礎知識 - Binder 和鎖競爭解讀[10]]
  11. [Systrace 基礎知識 - Triple Buffer 解讀[11]]
  12. Systrace 基礎知識 - CPU Info 解讀[12]

CPU 區域圖例

下面是高通驍龍 845 手機 Systrace 對應的 Kernel 中的 CPU Info 區域(底下的一些這里不講,主要是講 Kernel CPU 信息)

CPU 區域圖例

Systrace 中 CPU Info 一般在最上面,里面經常會用到的信息包括:

  1. CPU 頻率變化情況
  2. 任務執行情況
  3. 大小核的調度情況
  4. CPU Boost 調度情況

總的來說,Systrace 中的 Kernel CPU Info 這里一般是看任務調度信息,查看是否是頻率或者調度導致當前任務出現性能問題,舉例如下:

  1. 某個場景的任務執行比較慢,我們就可以查看是不是這個任務被調度到了小核?
  2. 某個場景的任務執行比較慢,當前執行這個任務的 CPU 頻率是不是不夠?
  3. 我的任務比較特殊,比如指紋解鎖,能不能把我這個任務放到大核去跑?
  4. 我這個場景對 CPU 要求很高,我能不能要求在我這個場景運行的時候,限制 CPU 最低頻率?

與 CPU 運行信息相關的內容在 Systrace 基礎知識 -- 分析 Systrace 預備知識[13] 這篇文章里面有詳細的講解,不熟悉的同學可以配合這篇文章一起食用

核心架構

簡單來說目前的手機 CPU 按照核心數和架構來說,可以分為下面三類:

  1. 非大小核架構
  2. 大小核架構
  3. 大中小核架構

目前的大部分 CPU 都是大小核架構,當然也有一些 CPU 是大中小核架構,比如高通驍龍 855\865,也有少部分 CPU 是非大小核架構

下面就來說說各種架構的區別,方便大家后續查看 Systrace

非大小核架構

很早的機器 CPU 只有雙核心或者四核心的時候,一般只有一種核心架構,也就是說這四個核心或者兩個核心是同構的,相同的頻率,相同的功耗,一起開啟或者關閉;有些高通的中低端處理器也會使用同構的八核心處理器,比如高通驍龍 636

現在的大部分機器已經不使用非大小核的架構了

大小核架構

現在的 CPU 一般采用 8 核心,八個核心中,CPU 0-3 一般是小核心,CPU 4-7,如下圖中 Systrace 中就是按照這個排列的

小核心一般來說主頻低,功耗也低,使用的一般是 arm A5X 系列,比如高通驍龍 845,小核心是由四個 A55 (最高主頻 1.8GHz ) 組成

大核心一般來說最高主頻比較高,功耗相對來說也會比較高,使用的一般是 arm A7X 系列,比如高通驍龍 845,大核心就是由四個 A75(最高主頻 2.8GHz)組成

下圖就是 845 的 CPU

當然大小核架構中還有一些變種,比如高通驍龍 636 (4 小核 + 2 大核)或者高通驍龍 710 (6 小核 + 2 大核),宗旨還是不變,「大核心用來支持高負載場景,小核心用來日常使用,至于夠不夠用,就看你舍不舍得花銀子,畢竟一分價錢一分貨,高通爸爸也不是做福利的」

下面這些高通的主流大小核處理器的參數如下

高通處理器參數

大中小核架構

部分 CPU 比較另辟蹊徑,選擇了大中小核的架構,比如高通驍龍 855 8 核 (1 個 A76 的大核+3 個 A76 的中核 + 4 個 A55 的小核)和之前的的 MTK X30 10 核 (2 個 A73 的大核 + 4 個 A53 的中核 + 4 個 A35 的小核)以及麒麟 980 8 核 (2 個 A76 的大核 + 2 個 A76 的中核 + 4 個 A55 的小核)

相比大小核架構,大中小核架構中的大核可以理解為超大核(高通稱之為 Gold +) ,這個超大核的個數一般比較少(1-2 個),主頻一般會比較高,功耗相對也會高很多,這個是用來處理一些比較繁重的任務

下圖是 855、845 和麒麟 980 的對比

855、845 和麒麟 980 的對比

順帶提一嘴,今年的高通驍龍 865 依然是大中小核的架構,大核和中核用的是 A77 架構,小核用的是 A55,大核和中核最高頻率不一樣,「大核只有一個,主頻到 2.8GHz」,不知道 865 Plus 會不會搞到 3GHz

865

綁核

綁核,顧名思義就是「把某個任務綁定到某個或者某些核心上,來滿足這個任務的性能需求」

  1. 任務本身負載比較高,需要在大核心上面才能滿足時間要求
  2. 任務本身不想被頻繁切換,需要綁定在某一個核心上面
  3. 任務本身不重要,對時間要求不高,可以綁定或者限制在小核心上面運行

上面是一些綁核的例子,目前 Android 中綁核操作一般是由系統來實現的,常用的有三種方法

配置 CPUset

使用 CPUset 子系統可以限制某一類的任務跑在特定的 CPU 或者 CPU 組里面,比如下面,Android 中會劃分一些默認的 CPU 組,廠商可以針對不同的 CPU 架構進行定制,目前默認劃分

  1. system-background 一些低優先級的任務會被劃分到這里,只能跑到小核心里面
  2. foreground 前臺進程
  3. top-app 目前正在前臺和用戶交互的進程
  4. background 后臺進程
  5. foreground/boost 前臺 boost 進程,通常是用來聯動的,現在已經沒有用到了,之前的時候是應用啟動的時候,會把所有 foreground 里面的進程都遷移到這個進程組里面

每個 CPU 架構對應的 CPUset 的配置都不一樣,每個廠商也會有不同的策略在里面,比如下面就是一個 Google 官方默認的配置,各位也可以查看對應的節點來查看自己的 CPUset 組的配置

//官方默認配置
write /dev/CPUset/top-app/CPUs 0-7
write /dev/CPUset/foreground/CPUs 0-7
write /dev/CPUset/foreground/boost/CPUs 4-7
write /dev/CPUset/background/CPUs 0-7
write /dev/CPUset/system-background/CPUs 0-3
// 自己查看
adb shell cat /dev/CPUset/top-app/CPUs
0-7

對應的,可以在每個 CPUset 組的 tasks 節點下面看有哪些進程和線程是跑在這個組里面的


$ adb shell cat /dev/CPUset/top-app/tasks
1687
1689
1690
3559

需要注意每個任務跑在哪個組里面,是動態的,并不是一成不變的,有權限的進程就可以改

部分進程也可以在啟動的時候就配置好跑到哪個進程里面,下面是 lmkd 的啟動配置,writepid /dev/CPUset/system-background/tasks 這一句把自己安排到了 system-background 這個組里面

service lmkd /system/bin/lmkd
    class core
    user lmkd
    group lmkd system readproc
    capabilities DAC_OVERRIDE KILL IPC_LOCK SYS_NICE SYS_RESOURCE BLOCK_SUSPEND
    critical
    socket lmkd seqpacket 0660 system system
    writepid /dev/CPUset/system-background/tasks

大部分 App 進程是根據狀態動態去變化的,在 Process 這個類中有詳細的定義

android/os/Process.java

/**
 * Default thread group -
 * has meaning with setProcessGroup() only, cannot be used with setThreadGroup().
 * When used with setProcessGroup(), the group of each thread in the process
 * is conditionally changed based on that thread's current priority, as follows:
 * threads with priority numerically less than THREAD_PRIORITY_BACKGROUND
 * are moved to foreground thread group.  All other threads are left unchanged.
 * @hide
 */
public static final int THREAD_GROUP_DEFAULT = -1;

/**
 * Background thread group - All threads in
 * this group are scheduled with a reduced share of the CPU.
 * Value is same as constant SP_BACKGROUND of enum SchedPolicy.
 * FIXME rename to THREAD_GROUP_BACKGROUND.
 * @hide
 */
public static final int THREAD_GROUP_BG_NONINTERACTIVE = 0;

/**
 * Foreground thread group - All threads in
 * this group are scheduled with a normal share of the CPU.
 * Value is same as constant SP_FOREGROUND of enum SchedPolicy.
 * Not used at this level.
 * @hide
 **/
private static final int THREAD_GROUP_FOREGROUND = 1;

/**
 * System thread group.
 * @hide
 **/
public static final int THREAD_GROUP_SYSTEM = 2;

/**
 * Application audio thread group.
 * @hide
 **/
public static final int THREAD_GROUP_AUDIO_APP = 3;

/**
 * System audio thread group.
 * @hide
 **/
public static final int THREAD_GROUP_AUDIO_SYS = 4;

/**
 * Thread group for top foreground app.
 * @hide
 **/
public static final int THREAD_GROUP_TOP_APP = 5;

/**
 * Thread group for RT app.
 * @hide
 **/
public static final int THREAD_GROUP_RT_APP = 6;

/**
 * Thread group for bound foreground services that should
 * have additional CPU restrictions during screen off
 * @hide
 **/
 public static final int THREAD_GROUP_RESTRICTED = 7;

在 OomAdjuster 中會動態根據進程的狀態修改其對應的 CPUset 組, 詳細可以自行查看 OomAdjuster 中 computeOomAdjLocked、updateOomAdjLocked、applyOomAdjLocked 的執行邏輯(Android 10)

配置 affinity

使用 affinity 也可以設置任務跑在哪個核心上,其系統調用的 taskset, taskset 用來查看和設定“CPU 親和力”,其實就是查看或者配置進程和 CPU 的綁定關系,讓某進程在指定的 CPU 核上運行,即是“綁核”。

taskset 的用法

「顯示進程運行的 CPU」

taskset -p pid

注意,此命令返回的是十六進制的,轉換成二進制后,每一位對應一個邏輯 CPU,低位是 0 號 CPU,依次類推。如果每個位置上是 1,表示該進程綁定了該 CPU。例如,0101 就表示進程綁定在了 0 號和 3 號邏輯 CPU 上了

「綁核設定」

taskset -pc 3  pid    表示將進程pid綁定到第3個核上
taskset -c 3 command   表示執行 command 命令,并將 command 啟動的進程綁定到第3個核上。

Android 中也可以使用這個系統調用,把任務綁定到某個核心上運行。部分較老的內核里面不支持 CPUset,就會用 taskset 來設置

調度算法

在 Linux 的調度算法中修改調度邏輯,也可以讓指定的 task 跑在指定的核上面,部分廠家的核調度優化就是使用的這種方法,這里就不具體來講了

鎖頻

正常情況下,CPU 的調度算法都可以滿足日常的使用,但是在 Android 中的部分場景里面,單純依靠調度器,可能會無法滿足這個場景對性能的要求。比如說應用啟動場景,如果讓調度器去拉頻率遷核,可能就會有一定的延遲,比如任務先在小核跑,發現小核頻率不夠,那就把小核頻率往上拉,拉上去之后發現可能還是不夠,經過幾次一直拉到最高發現還是不夠,然后把這個任務遷移到中核,頻率也是一次一次拉,拉到最高發現還是不夠,最好遷移到大核去做。這樣一套下來,時間過去不少不說,啟動速度也不是最快的

基于這種情況的考慮,系統中一般都會在這種特殊場景直接暴力拉核,將硬件資源直接拉到最高去運行,比如 CPU、GPU、IO、BUS 等;另外也會在某些場景把某些資源限制使用,比如發熱太嚴重的時候,需要限制 CPU 的最高頻率,來達到降溫的目的;有時候基于功耗的考慮,也會限制一些資源在某些場景的使用

目前 Android 系統一般會在下面幾個場景直接進行鎖頻(不同廠家也會自己定制)

  1. 應用啟動
  2. 應用安裝
  3. 轉屏
  4. 窗口動畫
  5. List Fling
  6. Game

以 高通平臺為例,在 CPU Info 中我們也可以看到鎖頻的情況

鎖頻 CPU 狀態

CPU info 中還有標識 CPU 狀態的標記,如下圖所示,CPU 狀態有 0 ,1,2,3 這四種

CPU 狀態

之前的 CPU 支持熱插拔,即不用的時候可以直接關閉,不過目前的 CPU 都不支持熱插拔,而是使用 C-State

下面是摘抄的其他平臺的支持 C0-C4 的處理器的狀態和功耗狀態,Android 中不同的平臺表現不一致,大家可以做一下參考

1 . C0 狀態(激活)

a . 這是 CPU 最大工作狀態,在此狀態下可以接收指令和處理數據

b . 所有現代處理器必須支持這一功耗狀態

2 . C1 狀態(掛起)

a . 可以通過執行匯編指令“ HLT (掛起)”進入這一狀態

b . 喚醒時間超快?。斓街恍?10 納秒?。?/p>

c . 可以節省 70% 的 CPU 功耗

d . 所有現代處理器都必須支持這一功耗狀態

3 . C2 狀態(停止允許)

a . 處理器時鐘頻率和 I/O 緩沖被停止

b . 換言之,處理器執行引擎和 I/0 緩沖已經沒有時鐘頻率

c . 在 C2 狀態下也可以節約 70% 的 CPU 和平臺能耗

d . 從 C2 切換到 C0 狀態需要 100 納秒以上

4 . C3 狀態(深度睡眠)

a . 總線頻率和 PLL 均被鎖定

b . 在多核心系統下,緩存無效

c . 在單核心系統下,內存被關閉,但緩存仍有效可以節省 70% 的 CPU 功耗,但平臺功耗比 C2 狀態下大一些

d . 喚醒時間需要 50 微妙

Systrace 中的詳細信息

Systrace 我們一般用 Chrome 打開,轉換成圖形化信息之后更加方便從整體去看,但其實 Systrace 也可以以文本的方式打開,也可以看到一些詳細的信息。

比如下面就是一條標識 CPU 調度的 Message,解析的時候,里面的信息會被解析到各個模塊

appEventThread-8193  [001] d..2 1638545.400415: sched_switch: prev_comm=appEventThread prev_pid=8193 prev_prio=97 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120

詳細來看

appEventThread-8193    -- 標識 TASK-PID
[001]                  -- 標識是哪個 CPU ,這里是 cpu0
d..2                   -- 這是四個位,每個位分別對應 irqs-off、need-resched、hardirq/softirq、preempt-depth
1638545.400415         -- 標識 delay TIMESTAMP
sched_switch ...到最后  -- 標識信息區,里面包含前一個任務描述,前一個任務的 pid,前一個任務的優先級 ,當前任務,當前任務 pid,當前任務優先級

另外里面仔細看也可以看到許多有趣的輸出,可以加深對調度的理解

  1. sched_waking: comm=kworker/u16:4 pid=17373 prio=120 target_cpu=003
  2. sched_blocked_reason: pid=17373 iowait=0 caller=rpmh_write_batch+0x638/0x7d0
  3. cpu_idle: state=0 cpu_id=3
  4. softirq_raise: vec=6 [action=TASKLET]
  5. cpu_frequency_limits: min=1555200 max=1785600 cpu_id=0
  6. cpu_frequency_limits: min=710400 max=2419200 cpu_id=4
  7. cpu_frequency_limits: min=825600 max=2841600 cpu_id=7

參考

  1. 綁定 CPU 邏輯核心的利器——taskset[17]
  2. CPU 電源狀態[18]

Reference

[1]Systrace 簡介: https://www.androidperformance.com/2019/05/28/Android-Systrace-About/

[2]Systrace 基礎知識 - Systrace 預備知識: https://www.androidperformance.com/2019/07/23/Android-Systrace-Pre/

[3]Systrace 基礎知識 - Why 60 fps ?: https://www.androidperformance.com/2019/05/27/why-60-fps/

[4]Systrace 基礎知識 - SystemServer 解讀: https://www.androidperformance.com/2019/06/29/Android-Systrace-SystemServer/

[5]Systrace 基礎知識 - SurfaceFlinger 解讀: https://www.androidperformance.com/2020/02/14/Android-Systrace-SurfaceFlinger/

[6]Systrace 基礎知識 - Input 解讀: https://www.androidperformance.com/2019/11/04/Android-Systrace-Input/

[7]Systrace 基礎知識 - Vsync 解讀: https://www.androidperformance.com/2019/12/01/Android-Systrace-Vsync/

[8]Systrace 基礎知識 - Vsync-App :基于 Choreographer 的渲染機制詳解: https://androidperformance.com/2019/10/22/Android-Choreographer/

[9]Systrace 基礎知識 - MainThread 和 RenderThread 解讀: https://www.androidperformance.com/2019/11/06/Android-Systrace-MainThread-And-RenderThread/

[10]Systrace 基礎知識 - Binder 和鎖競爭解讀: https://www.androidperformance.com/2019/12/06/Android-Systrace-Binder/

[11]Systrace 基礎知識 - Triple Buffer 解讀: https://www.androidperformance.com/2019/12/15/Android-Systrace-Triple-Buffer

[12]Systrace 基礎知識 - CPU Info 解讀: https://www.androidperformance.com/2019/12/21/Android-Systrace-CPU

[13]Systrace 基礎知識 -- 分析 Systrace 預備知識: https://www.androidperformance.com/2019/07/23/Android-Systrace-Pre/

[14]綁定 CPU 邏輯核心的利器——taskset: https://blog.csdn.net/breaksoftware/article/details/79160916

[15]CPU 電源狀態: http://www.voidcn.com/article/p-kcjkqmld-bmg.html


https://mp.weixin.qq.com/s/XIiDY3ecGCdad2o7ainQ7w

Android Systrace 基礎知識(11) - Triple Buffer 解讀

發布于:3月以前  |  514次閱讀  |  詳細內容 ?

Android Systrace 基礎知識(7) - Vsync 解讀

發布于:3月以前  |  528次閱讀  |  詳細內容 ?

Android Systrace 基礎知識(6) - Input 解讀

發布于:3月以前  |  511次閱讀  |  詳細內容 ?

Android Systrace 基礎知識(5) - SurfaceFlinger 解讀

發布于:3月以前  |  533次閱讀  |  詳細內容 ?

Android Systrace 基礎知識(4) - SystemServer 解讀

發布于:3月以前  |  484次閱讀  |  詳細內容 ?

Android Systrace 基礎知識(3) - Why 60 fps ?

發布于:3月以前  |  428次閱讀  |  詳細內容 ?

Android Systrace 基礎知識 -- Systrace 簡介

發布于:3月以前  |  493次閱讀  |  詳細內容 ?

所屬標簽

最多閱讀

簡化Android的UI開發 2年以前  |  515113次閱讀
Android 深色模式適配原理分析 1年以前  |  26416次閱讀
Android 樣式系統 | 主題背景覆蓋 1年以前  |  7953次閱讀
Android Studio 生成so文件 及調用 1年以前  |  5587次閱讀
30分鐘搭建一個android的私有Maven倉庫 3年以前  |  4751次閱讀
Android設計與開發工作流 2年以前  |  4413次閱讀
Google Enjarify:可代替dex2jar的dex反編譯 3年以前  |  4397次閱讀
Android多渠道打包工具:apptools 3年以前  |  4028次閱讀
移動端常見崩潰指標 2年以前  |  4014次閱讀
Google Java編程風格規范(中文版) 3年以前  |  3942次閱讀
Android-模塊化-面向接口編程 1年以前  |  3857次閱讀
Android內存異常機制(用戶空間)_NE 1年以前  |  3824次閱讀
Android UI基本技術點 3年以前  |  3790次閱讀
Android死鎖初探 2年以前  |  3734次閱讀

手機掃碼閱讀
18禁止午夜福利体验区,人与动人物xxxx毛片人与狍,色男人窝网站聚色窝
<蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>