Linux 性能分析總結之 CPU 上下文切換(二)

0x00 前言

上一篇筆記中我講到了,在尋找 CPU 的性能瓶頸的問題的時候,首先會查看整臺機器的平均負載是否高,而後再使用 pidstat 等工具判斷究竟是哪一種狀況致使的平均負載升高,主要狀況有三種:函數

  • CPU 密集型
  • IO 密集型
  • 大量進程的場景

前面兩種狀況咱們都很好理解,可是大量的進程怎麼也會致使 CPU 出現瓶頸呢?這是由於咱們的 CPU 核心在執行任務的時候,仍然是單任務的,只不過它執行的很快,讓每一個進程交替着執行,因此在人類眼中看上去像是多個線程在並行執行。然而不一樣的線程交替的切換着執行時須要成本的,當進程數量不少的時候,CPU Context Swith 就很頻繁了,那麼就會致使 CPU 出現性能瓶頸。CPU Context Swith 能夠分爲如下幾種場景:工具

  • 進程上下文切換
  • 線程上下文切換
  • 中斷上下文切換

0x01 進程上下文切換

首先,Linux 按照特權等級,把進程的運行空間分爲內核態和用戶態,CPU 特權等級爲 0-3 數字越小權限越高。
clipboard.png性能

那麼問題來了,因爲 Linux 如今只用到了兩個特權等級,分別是 Ring 0 內核態和 Ring 3 用戶態,因此運行在不一樣的特權等級上的進程上下文切換主要有兩種:spa

  • 用戶態進程之間的切換
  • 用戶態進程陷入到內核態,即系統調用

那用戶態進程陷入內核態進程與用戶態空間之間的切換有何不一樣呢?不一樣之處在於用戶態在進行系統調用的時候,會發生兩次 CPU 的上下文切換,分別是:線程

  1. 用戶態切陷入到內核態執行
  2. 內核態進程執行完成後再恢復爲原來的用戶態的進程執行

那麼說明了在系統調用的時候並不會切換本來的用戶態的進程,它只是進行了系統調用(即切換到內核態)又恢復了,因此咱們把系統調用成爲特權模式切換,用戶態之間的進程成爲上下文切換對象

系統調用與上下文切換有何區別?

上下文切換相比系統調用會保存進程的虛擬內存和棧,因此會消耗更多的時間blog

什麼時候會進行進程上下文切換?

  1. CPU 時間片結束,CPU 是劃分爲多個時間片的給不一樣進程使用的
  2. 進程運行須要的資源不夠,如等待IO,Memory insufficient 等等
  3. 進程主動掛起,如 sleep 函數
  4. 有優先級更高的進程執行,如硬中斷

0x02 線程上下文切換

線程與進程的區別是什麼?線程是調度的基本單位,進程是資源擁有的基本單位。也就是說線程是實際上幹活的,也是內核實際調度的對象,可是幹活你須要工具和場地,而進程就是給線程提供了虛擬內存、全局變量等資源。因此能夠這麼理解:進程

  • 進程 = 全部線程 + 資源
  • 若是進程只有一個線程,那麼能夠認爲這個線程就表明整個進程
  • 若是一個進程有多個線程,全部線程共享這個進程的資源,在上下文切換的時候這些資源也不須要切換
  • 線程有本身的私有數據,如 stack,Register等,這些須要保存

那麼線程的狀況分爲兩種:事件

  1. 先後線程屬於一個進程,那麼資源是共享的,因此只須要切換線程的私有數據
  2. 若是先後線程屬於不一樣的進程,那麼切換的狀況和進程是同樣的

0x03 中斷上下文切換

中斷是外部事件對 CPU 執行過程打的打斷,中斷程序也是須要執行的,它會保存被打斷的進程的狀態,這樣中斷程序執行結束了後原來的進程就還能接着執行,那麼天然中斷也須要上下文切換,也會消耗 CPU 的資源。可是因爲中斷並不涉及到切換用戶態進程,因此進程的資源是不須要保存和恢復的。ip

0x04 總結

從上個筆記中我說到了根據 CPU 升高的狀況下,會有三種緣由致使 CPU使用狀況升高。這裏我接着針對的是第三種大量進程切換的狀況,而這種狀況又能夠分爲三種狀況,分別是:

  • 進程上下文切換(進程切換就是特殊狀況的線程切換)

    • 系統調用
    • 進程上下文切換
  • 線程上線文切換
  • 中斷上下文切換
相關文章
相關標籤/搜索