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并发编程的艺术》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容

  • 前言 在Linux性能分析-平均负载中,提到过一种导致平均负载升高的情况,就是有大量进程或线程等待cpu调度。 为...
    ging_efcf阅读 255评论 0 0
  • 怎么查看系统的上下文切换情况 通过前面学习我们知道,过多的上下文切换,会把 CPU 时间消耗在寄存器、内核栈以及虚...
    tracy_668阅读 381评论 0 1
  • 怎么查看系统的上下文切换情况 过多的上下文切换,会把 CPU 时间消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢...
    coderljx阅读 257评论 0 0
  • 既然我们知道频繁CPU上下文切换会导致平均负载升高,那么如何排除问题呢? 使用性能监控工具vmstat可以查看上下...
    Java程序员YY阅读 1,098评论 0 0
  • 理解CPU 上下文切换 根据任务的不同,CPU 的上下文切换就可以分为几个不同的场景,也就是进程上下文切换、线程上...
    wayyyy阅读 804评论 0 0