Linux—CPU核數、上下文切換介紹及pidstat等命令詳解


技術公眾號:后端技術解憂鋪
關注微信公眾號:CodingTechWork,一起學習進步。

引言

並發編程

  並發編程的目的是為了改善串行程序執行慢問題,但是,並不是啟動更多線程就能夠讓程序執行更快。因為在並發時,容易受到軟硬件資源等限制,從而導致上下文切換慢,頻繁的上下文切換導致並發程序執行起來反而不如串行程序,違背了讓程序運行得更快一些這個最初的夢想。

單核和多核CPU

  在介紹上下文切換前,我們先來了解一下計算機CPU的單核和多核概念。
  最開始的單核CPU比較死腦,在通電時CPU就執行存儲塊中的指定地址的指令,如果想要執行內存塊其他地方的代碼必須調整總線位置才可以執行,這就阻塞程序了,期間只能執行某一個程序。后來,英特爾演進了一種叫做時間軸的工作方式,增加晶體管,CPU工作效率提高,並基於時鍾電路控制CPU跳轉到指定地址,借助操作系統來利用時鍾電路控制CPU的跳轉。
  多核集成在一個芯片里,由多個CPU組成,多核通過內部總線交互和共享數據,其中會有一個核專門分配給操作系統用,由操作系統分配資源及控制CPU執行程序。

windows查看核數

  打開命令行模式,可以利用Win+r鍵打開運行,然后輸入cmd
除了直接使用systeminfo命令,下面我們介紹wmic命令來查看計算機相關信息。

  1. 輸入wmic,進入命令行環境
  2. cpu get Name:查看計算機的cpu信息
  3. cpu get NumberOfCores:查看計算機的cpu核數
  4. cpu get NumberOfLogicalProcessors:查看計算機的cpu線程數
C:\Users\Lenovo>wmic
wmic:root\cli>cpu get Name
Name
Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz

wmic:root\cli>cpu get NumberOfCores
NumberOfCores
6

wmic:root\cli>cpu get NumberOfLogicalProcessors
NumberOfLogicalProcessors
12

wmic:root\cli>

linux查看核數

  一般linux的CPU相關信息都是存儲在/proc/cpuinfo內,內存信息存儲在/proc/meminfo中。

  1. cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l:查看物理CPU個數
  2. cat /proc/cpuinfo| grep "cpu cores"| uniq:查看單個CPU核數
  3. cat /proc/cpuinfo| grep "processor"| wc -l:查看邏輯CPU個數
  4. cat /proc/meminfo| grep MemTotal:查看內存大小
[linux@01 ~]$ cat /proc/cpuinfo| grep "cpu cores"| uniq
cpu cores       : 1
[linux@01 ~]$ cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l
16
[linux@01 ~]$ cat /proc/cpuinfo| grep "processor"| wc -l
16
[linux@01 ~]$ cat /proc/meminfo| grep MemTotal
MemTotal:       32780412 kB

上下文切換

上下文切換的介紹

  我們對於單核和多核不陌生了,自己的電腦或者使用的機器總是希望核數越多越好,畢竟多核能夠支持更好的多線程並發。當然,單核處理器也支持多線程執行代碼,CPU是通過給每個線程分配CPU時間片來實現。
  時間片就是CPU分配給各個線程的時間,那單核是如何實現多線程並發執行的呢?那是因為時間片非常短(一般是幾十毫秒),CPU通過切換線程交替執行,給你一種錯覺好像是多個線程同時執行了。
  CPU通過時間片來執行多線程執行,當前任務執行一個時間片后切換到下一個任務繼續執行,在切換任務前呢,其實CPU會保存該任務的狀態,這樣在下次切回該任務時,可以再加載這個任務的狀態,繼續執行(其實也就是保存當前線程的運行位置,同時呢,會加載需要恢復的線程環境相關信息。)。任務從保存到再加載的過程,這就是一次上下文切換的過程。
  上下文切換一旦頻繁,必定消耗CPU資源,必定耗時,並發的性能將會受到影響。如何減少?

上下文切換的減少

  減少上下文切換的方法有無鎖並發編程、CAS算法、使用最少線程和使用協程方式。

  • 無鎖並發編程:多線程競爭鎖時,大量的任務交替執行,會引起上下文切換,在多線程處理數據時,我們可以使用一些無鎖方式來處理共享數據,比如將數據的ID按照Hash算法取模進行分段,這樣不同的線程去處理不同分段的數據。
  • CAS算法:JAVA的Atomic包就使用了CAS算法來更新數據,無需加鎖。
  • 使用最少線程:在程序開發過程中,要避免創建不必要的線程,如並發任務很少,若創建了很多線程來處理任務,可能在程序運行時,大部分線程都是出於等待閑置的狀態。比如減少線上大量的WAITING線程,我們可以通過jstack [pid] > dumpName將某個進程的線程信息dump到dumpName文件中,然后通過篩選(grep java.lang.Thread.State dumpName | awk '{print $2$3$4$5}' | sort | uniq -c)出多少個線程處於WAITING狀態。或者直接通過jstack -l [pid]| grep BLOCKEDjstack -l [pid]| grep WAITING等命令查看該進程的線程信息。
  • 協程:在單線程里實現多個任務的調度,並在單個線程里面維持多個任務的切換。

上下文切換的查看

  我們可以使用vmstat命令和pidstat命令查看上下文切換的次數等信息。

vmstat命令

  vmstat命令是Virtual Memory Statistics虛擬內存統計的縮寫,可以對操作系統的虛擬內存、進程、CPU活動等進行監控統計。

vmstat命令參數詳解

[linux@01 ~]$ vmstat -help

Usage:
 vmstat [options] [delay [count]]

Options:
 -a, --active           active/inactive memory
 -f, --forks            number of forks since boot
 -m, --slabs            slabinfo
 -n, --one-header       do not redisplay header
 -s, --stats            event counter statistics
 -d, --disk             disk statistics
 -D, --disk-sum         summarize disk statistics
 -p, --partition <dev>  partition specific statistics
 -S, --unit <char>      define display unit
 -w, --wide             wide output
 -t, --timestamp        show timestamp

 -h, --help     display this help and exit
 -V, --version  output version information and exit

For more details see vmstat(8).

比較常用的直接使用vmstat a,其中a代表的是多少秒實時顯示。

vmstat 實時統計整體情況

語法

  • vmstat [count]

參數說明

  • count:表示統計間隔。

示例

[linux@01 ~]$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 13223320 146732 1982108    0    0     0     3    0    0  0  0 99  0  0
 1  0      0 13222504 146732 1982108    0    0     0   172  747 1224  0  0 99  0  0
 0  0      0 13222696 146732 1982108    0    0     0    44 1078 1464  0  0 99  0  0
 0  0      0 13223492 146732 1982108    0    0     0     0  749 1189  0  0 100  0  0
 0  0      0 13223260 146732 1982092    0    0     0    16  789 1272  0  0 100  0  0
 0  0      0 13223620 146732 1981996    0    0     0     0 1359 1589  0  0 99  0  0
 0  0      0 13224364 146732 1981996    0    0     0   156  817 1279  0  0 100  0  0
 0  0      0 13222488 146732 1981996    0    0     0    32  792 1292  0  0 100  0  0

pidstat命令

  vmstat可以對操作系統進行整體情況統計,但是無法對某個進程進行統計分析,下面學習一下pidstat命令,可以針對整體或者某個進程進行分析。

pidstat安裝

  pidstat命令是對linux系統監控的一種命令,使用該命令可以對linux進程數據進行監控,可以輸出每個受內核管理的任務相關信息,而pidstat是sysstat軟件套件的一部分,所以首先得安裝該命令。
  如果是centos系統,使用yum install sysstat安裝即可。

pidstat命令參數詳解

[linux@01 ~]$ pidstat -help
Usage: pidstat [ options ] [ <interval> [ <count> ] ]
Options are:
[ -d ] [ -h ] [ -I ] [ -l ] [ -r ] [ -s ] [ -t ] [ -U [ <username> ] ] [ -u ]
[ -V ] [ -w ] [ -C <command> ] [ -p { <pid> [,...] | SELF | ALL } ]
[ -T { TASK | CHILD | ALL } ]

其中:

  • interval:表示間隔多久統計一次數據,可選的參數。
  • count:表示統計多少次,可選參數,若只傳了interval,而無count,則默認無限次統計次數。

pidstat cpu統計

語法

  • 全量:pidstat -u [interval] [count]或者默認pidstat [interval] [count]
  • 某個任務:pidstat -p <pid> [interval] [count]


全量任務cpu統計示例

[linux@01 ~]$ pidstat
Linux 3.10.0-514.el7.x86_64 (01)  03/09/2021      _x86_64_        (16 CPU)

08:45:48 AM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
08:45:48 AM     0         1    0.00    0.00    0.00    0.00    14  systemd
08:45:48 AM     0         2    0.00    0.00    0.00    0.00    15  kthreadd
08:45:48 AM     0         3    0.00    0.00    0.00    0.00     0  ksoftirqd/0
08:45:48 AM     0         7    0.00    0.00    0.00    0.00     0  migration/0
08:45:48 AM     0         9    0.00    0.01    0.00    0.01    15  rcu_sched
08:45:48 AM     0        10    0.00    0.00    0.00    0.00     0  watchdog/0
08:45:48 AM     0        11    0.00    0.00    0.00    0.00     1  watchdog/1
08:45:48 AM     0        12    0.00    0.00    0.00    0.00     1  migration/1
08:45:48 AM     0        13    0.00    0.00    0.00    0.00     1  ksoftirqd/1


某個pid任務cpu統計示例

[linux@01 ~]$ pidstat -u -p 27680 1 
Linux 3.10.0-514.el7.x86_64 (01)  03/09/2021      _x86_64_        (16 CPU)

09:14:19 AM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
09:14:20 AM  1000     27680    1.00    0.00    0.00    1.00     8  java
09:14:21 AM  1000     27680    0.00    0.00    0.00    0.00     8  java
09:14:22 AM  1000     27680    0.00    0.00    0.00    0.00     8  java
09:14:23 AM  1000     27680    0.00    0.00    0.00    0.00     8  java

統計參數詳解

  • UID:表示監視任務的真實用戶標識編號。
  • PID:表示被監控任務的進程號
  • %usr:表示該任務在用戶態應用程序執行時的CPU使用率,該字段的CPU計算時間不包括在虛擬處理器中花去的時間。(用戶層面)
  • %system :表示該任務在內核態執行時的CPU使用率。(系統層面)
  • %guest:表示該任務在虛擬機處理器上執行時的CPU使用率。(虛擬層面)。
  • %CPU:表示該任務總的CPU使用率。在多處理器環境中,如果帶上-I參數,CPU使用率的計算會除以機器的CPU數量。
  • CPU:表示正在運行該任務的處理器編號。
  • Command:表示該任務的執行命令名稱。

pidstat I/O統計

語法

  • pidstat -d -p <pid>

示例

[linux@01 ~]$ pidstat -d -p 27680
Linux 3.10.0-514.el7.x86_64 (01)  03/09/2021      _x86_64_        (16 CPU)

08:52:55 AM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
08:52:55 AM  1000     27680      0.00      0.01      0.00  java

統計參數詳解

  • UID:表示監視任務的真實用戶標識編號。
  • PID:表示被監控任務的進程號
  • kB_rd/s:表示該任務從硬盤上的讀取速度,rd表示read
  • kB_wr/s:表示該任務向硬盤中的寫入速度,wr表示write
  • kB_ccwr/s :表示該任務寫入磁盤被取消的速度。ccwr表示cancel write
  • Command:表示該任務的執行命令名稱。

pidstat 內存統計

語法

  • pidstat -r -p <pid>

示例

[linux@01 ~]$ pidstat -r -p 27680
Linux 3.10.0-514.el7.x86_64 (01)  03/09/2021      _x86_64_        (16 CPU)

08:56:48 AM   UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command
08:56:48 AM  1000     27680      0.01      0.00 13124360 2489432   7.59  java

統計參數詳解

  • UID:表示監視任務的真實用戶標識編號。
  • PID:表示被監控任務的進程號。
  • minflt/s:表示從內存中加載數據時每秒出現的較小錯誤數目,這些不要求從磁盤載入內存頁面,其中minflt表示minor fault
  • majflt/s:表示從內存中加載數據時每秒出現的較大錯誤數目,這些要求從磁盤載入內存頁面,其中majflt表示major fault
  • VSZ:表示虛擬容量,整個進程的虛擬內存使用(單位:kb)
  • RSS:表示長期內存使用,任務的不可交換物理內存的使用量(單位:kb)
  • Command:表示該任務的執行命令名稱。

pidstat 間隔有限次數監控

語法

  • pidstat -p <pid> [interval] [count]

示例

[linux@01 ~]$ pidstat -p 27680 1 5
Linux 3.10.0-514.el7.x86_64 (01)  03/09/2021      _x86_64_        (16 CPU)

09:03:55 AM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
09:03:56 AM  1000     27680    0.00    0.00    0.00    0.00     8  java
09:03:57 AM  1000     27680    0.00    0.00    0.00    0.00     8  java
09:03:58 AM  1000     27680    1.00    0.00    0.00    1.00     8  java
09:03:59 AM  1000     27680    0.00    0.00    0.00    0.00     8  java
09:04:00 AM  1000     27680    0.00    0.00    0.00    0.00     8  java
Average:     1000     27680    0.20    0.00    0.00    0.20     -  java

pidstat 上下文切換統計

語法

  • pidstat -w <pid> [interval] [count]

示例

[linux@01 ~]$ pidstat -w -p 27680
Linux 3.10.0-514.el7.x86_64 (01)  03/09/2021      _x86_64_        (16 CPU)

09:11:15 AM   UID       PID   cswch/s nvcswch/s  Command
09:11:15 AM  1000     27680      0.00      0.00  java
[linux@01 ~]$ pidstat -w -p 27680 1 10
Linux 3.10.0-514.el7.x86_64 (01)  03/09/2021      _x86_64_        (16 CPU)

09:11:39 AM   UID       PID   cswch/s nvcswch/s  Command
09:11:40 AM  1000     27680      0.00      0.00  java
09:11:41 AM  1000     27680      0.00      0.00  java
09:11:42 AM  1000     27680      0.00      0.00  java
09:11:43 AM  1000     27680      0.00      0.00  java
09:11:44 AM  1000     27680      0.00      0.00  java
09:11:45 AM  1000     27680      0.00      0.00  java
09:11:46 AM  1000     27680      0.00      0.00  java
09:11:47 AM  1000     27680      0.00      0.00  java
09:11:48 AM  1000     27680      0.00      0.00  java
09:11:49 AM  1000     27680      0.00      0.00  java
Average:     1000     27680      0.00      0.00  java

統計參數詳解

  • UID:表示監視任務的真實用戶標識編號。
  • PID:表示被監控任務的進程號。
  • cswch/s:表示該任務每秒自願上下文切換次數,當某一任務處於阻塞等待時,將主動讓出自己的CPU資源。其中cswch表示context switch
  • nvcswch/s:表示該任務每秒非資源上下文切換次數,CPU分配給某一任務的時間片已經用完,因此將強迫該進程讓出CPU的執行權。其中nvcswch表示involuntary context switch
  • Command:表示該任務的執行命令名稱。

REF《Java並發編程的藝術》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM