2.2 CPU 上下文切换是什么意思?(下)

怎么查看系统的上下文切换情况

过多的上下文切换,会把 CPU 时间消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢复上,缩短进程真正运行的时间,成了系统性能大幅下降的一个 元凶。

使用 vmstat 这个工具,来查询系统的上下文切换情况。
vmstat 是一个常用的系统性能分析工具,主要用来分析系统的内存使用情况,也常用来分析 CPU 上下文切换和中断的次数。
vmstat 的使用示例:

[[email protected] ~]# vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache    si   so    bi     bo  in   cs us sy id  wa  st
 0  0      0 1068760 120384 612716    0    0     0     0   57   98  0  0 100  0  0

cs(context switch)是每秒上下文切换的次数。
in(interrupt)则是每秒中断的次数。
r(Running or Runnable)是就绪队列的长度,也就是正在运行和等待 CPU 的进程数。
b(Blocked)则是处于不可中断睡眠状态的进程数。

这个例子中的上下文切换次数 cs 是 98 次,而系统中断次数 in 则是 57 次,而就绪队列长度 r 和不可中断状态进程数 b 都是 0。

vmstat 只给出了系统总体的上下文切换情况,要想查看每个进程的详细情况,就需要使用我们前面提到过的 pidstat 了。给它加上 -w 选项,你就可以查看每个进程上下文切换的情况了。

每隔 5 秒输出 1 组数据
[[email protected] ~]# pidstat -w 5
Linux 4.20.0-1.el7.elrepo.x86_64 (doit)     07/12/2019     _x86_64_    (2 CPU)

04:28:40 PM   UID       PID   cswch/s nvcswch/s  Command
 04:28:45 PM     0         9      0.20      0.00  ksoftirqd/0
 04:28:45 PM     0        10      2.00      0.00  rcu_sched
 04:28:45 PM     0        11      0.40      0.00  migration/0
 04:28:45 PM     0        15      0.40      0.00  migration/1
 04:28:45 PM     0        27      0.20      0.00  khugepaged
 04:28:45 PM     0      3086      0.20      0.00  haveged
 04:28:45 PM     0      3104      9.98      0.00  qemu-ga
 04:28:45 PM     0      3492      1.00      0.00  httpd
 04:28:45 PM     0      6094      0.40      0.00  python
 04:28:45 PM     0     29541      5.39      0.00  kworker/1:0-events_power_efficient
 04:28:45 PM     0     29590      1.40      0.00  kworker/0:1-events
 04:28:45 PM     0     29716      0.20      0.20  pidstat

一个是 cswch ,表示每秒自愿上下文切换(voluntary context switches)的次数,另一个则是 nvcswch ,表示每秒非自愿上下文切换(non voluntary context switches)的次数。

所谓自愿上下文切换,是指进程无法获取所需资源,导致的上下文切换。比如说, I/O、内存等系统资源不足时,就会发生自愿上下文切换。
而非自愿上下文切换,则是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。比如说,大量进程都在争抢 CPU 时,就容易发生非自愿上下文切换。

案例分析

上下文切换频率是多少次才算正常呢?

sysbench  是一个多线程的基准测试工具,一般用来评估不同系统参数下的数据库负载情况。当然,在这次案例中,我们只把它当成一个异常进程来看,作用是模拟上下文切换过多的问题。

预先安装 sysbench 和 sysstat 包,如 apt install sysbench sysstat

操作和分析

首先,在第一个终端里运行 sysbench ,模拟系统多线程调度的瓶颈:

# 以 10 个线程运行 5 分钟的基准测试,模拟多线程切换的问题
[[email protected] ~]# sysbench --threads=10 --max-time=300 threads run
WARNING: --max-time is deprecated, use --time instead
sysbench 1.0.17 (using system LuaJIT 2.0.4)

Running the test with following options:
Number of threads: 10
Initializing random number generator from current time

Initializing worker threads...

Threads started!

在第二个终端运行 vmstat ,观察上下文切换情况:

[[email protected] ~]# 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
  6  0      0 1066924 120388 612752    0    0     0     0    7    3  0  0 100  0  0
  8  0      0 1066924 120388 612768    0    0     0     0 2472 1695514 17 82  1  0  0
  8  0      0 1066924 120388 612768    0    0     0     0 3062 1847851 17 83  1  0  0
  7  0      0 1066924 120388 612768    0    0     0     0 2093 1696907 16 82  2  0  0
cs 列的上下文切换次数从之前的 3 骤然上升到了 169 万。同时,注意观察其他几个指标:
r 列:就绪队列的长度已经到了 8,远远超过了系统 CPU 的个数 2,所以肯定会有大量的 CPU 竞争。
us(user)和 sy(system)列:这两列的 CPU 使用率加起来上升到了 100%,其中系统 CPU 使用率,也就是 sy 列高达 83%,说明 CPU 主要是被内核占用了。
in 列:中断次数也上升到了 1 万左右,说明中断处理也是个潜在的问题。

综合这几个指标,我们可以知道,系统的就绪队列过长,也就是正在运行和等待 CPU 的进程数过多,导致了大量的上下文切换,而上下文切换又导致了系统 CPU 的占用率升高。

那么到底是什么进程导致了这些问题呢?

在第三个终端再用 pidstat 来看一下, CPU 和进程上下文切换的情况

# 每隔 1 秒输出 1 组数据
  -w 参数表示输出进程切换指标,而 -u 参数则表示输出 CPU 使用指标

[[email protected] ~]# pidstat -w -u 1
 Linux 4.20.0-1.el7.elrepo.x86_64 (doit)     07/12/2019     _x86_64_    (2 CPU)

04:38:35 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
 04:38:36 PM     0     29730   33.00  167.00    0.00    0.00  200.00     0  sysbench

04:38:35 PM   UID       PID   cswch/s nvcswch/s  Command
 04:38:36 PM     0        10      3.00      0.00  rcu_sched
 04:38:36 PM     0        16      1.00      0.00  ksoftirqd/1
 04:38:36 PM     0      3104     10.00      0.00  qemu-ga
 04:38:36 PM     0      3492      1.00      0.00  httpd
 04:38:36 PM     0     29541     14.00      0.00  kworker/1:0-events_power_efficient
 04:38:36 PM     0     29590      2.00      0.00  kworker/0:1-mm_percpu_wq
 04:38:36 PM     0     29640      1.00      0.00  sshd
 04:38:36 PM     0     29714      1.00      0.00  kworker/u4:0-events_unbound
 04:38:36 PM     0     29742      1.00      0.00  pidstat
从 pidstat 的输出你可以发现,CPU 使用率的升高果然是 sysbench 导致的,它的 CPU 使用率已经达到了 200%。但上下文切换则是来自其他进程,自愿上下文切换频率最高的内核线程 kworker。

pidstat 输出的上下文切换次数,加起来也就几百,比 vmstat 的 139 万明显小了太多。这是怎么回事呢?难道是工具本身出了错吗?

pidstat 默认显示进程的指标数据,加上 -t 参数后, 才会输出线程的指标。

[[email protected] ~]# pidstat -wt 1
Linux 4.20.0-1.el7.elrepo.x86_64 (doit)     07/12/2019     _x86_64_    (2 CPU)

04:45:02 PM   UID      TGID       TID   cswch/s nvcswch/s  Command
 04:45:03 PM     0         9         -      2.91      0.00  ksoftirqd/0
 04:45:03 PM     0         -         9      2.91      0.00  |__ksoftirqd/0
 04:45:03 PM     0        10         -     10.68      0.00  rcu_sched
 04:45:03 PM     0         -        10     10.68      0.00  |__rcu_sched
 04:45:03 PM     0        16         -      0.97      0.00  ksoftirqd/1
 04:45:03 PM     0         -        16      0.97      0.00  |__ksoftirqd/1
 04:45:03 PM     0      3104         -      9.71      0.00  qemu-ga
 04:45:03 PM     0         -      3104      9.71      0.00  |__qemu-ga
 04:45:03 PM     0         -      3820      0.97      0.00  |__tuned
 04:45:03 PM     0      6094         -      0.97      0.00  python
 04:45:03 PM     0         -      6094      0.97      0.00  |__python
 04:45:03 PM     0         -     14238      0.97      0.00  |__node
 04:45:03 PM     0     29590         -      1.94      0.00  kworker/0:1-mm_percpu_wq
 04:45:03 PM     0         -     29590      1.94      0.00  |__kworker/0:1-mm_percpu_wq
 04:45:03 PM     0         -     29768  20572.82 100301.94  |__sysbench
 04:45:03 PM     0         -     29769  18718.45 110695.15  |__sysbench
 04:45:03 PM     0         -     29770  22306.80 104282.52  |__sysbench
 04:45:03 PM     0         -     29771  26055.34  86372.82  |__sysbench
 04:45:03 PM     0         -     29772  20498.06 102583.50  |__sysbench
 04:45:03 PM     0         -     29773  14956.31  81900.00  |__sysbench
 04:45:03 PM     0         -     29774  29092.23 112430.10  |__sysbench
 04:45:03 PM     0         -     29775  24825.24 110958.25  |__sysbench
 04:45:03 PM     0         -     29776  23862.14  95394.17  |__sysbench
 04:45:03 PM     0         -     29777  21125.24  87931.07  |__sysbench
 04:45:03 PM     0     29780         -     12.62      0.00  kworker/1:1-events_power_efficient
 04:45:03 PM     0         -     29780     12.62      0.00  |__kworker/1:1-events_power_efficient
 04:45:03 PM     0     29783         -      0.97      1.94  pidstat
 04:45:03 PM     0         -     29783      0.97      1.94  |__pidstat

虽然 sysbench 进程(也就是主线程)的上下文切换次数看起来并不多,但它的子线程的上下文切换次数却有很多。看来,上下文切换罪魁祸首,还是过多的sysbench 线程。
   在观察系统指标时,除了上下文切换频率骤然升高,还有一个指标也有很大的变化。是的,正是中断次数。中断次数也上升到了 1 万,但到底是什么类型的中断上升了,现在还不清楚。接下来继续抽丝剥茧找源头。既然是中断,我们都知道,它只发生在内核态,而 pidstat 只是一个进程的性能分析工具,并不提供任何关于中断的详细信息,怎样才能知道中断发生的类型呢?

没错,那就是从 /proc/interrupts 这个只读文件中读取。/proc 实际上是 Linux 的一个虚拟文件系统,用于内核空间与用户空间之间的通信。/proc/interrupts  就是这种通信机制的一部分,提供了一个只读的中断使用情况。

[[email protected] ~]# watch -d cat /proc/interrupts

Every 2.0s: cat /proc/interrupts                                         Fri Jul 12 16:49:08 2019

           CPU0       CPU1

 LOC:   83008310  107586288   Local timer interrupts
 SPU:          0          0   Spurious interrupts
 PMI:          0          0   Performance monitoring interrupts
 IWI:          0          1   IRQ work interrupts
 RTR:          0          0   APIC ICR read retries
 RES:    9169892    7079828   Rescheduling interrupts

观察一段时间,你可以发现,变化速度最快的是重调度中断(RES),这个中断类型表示,唤醒空闲状态的 CPU 来调度新的任务运行。这是多处理器系统(SMP)中,调度器用来分散任务到不同 CPU 的机制,通常也被称为处理器间中断(Inter-Processor Interrupts,IPI)。所以,这里的中断升高还是因为过多任务的调度问题,跟前面上下文切换次数的分析结果是一致的。

现在再回到最初的问题,每秒上下文切换多少次才算正常呢?
     这个数值其实取决于系统本身的 CPU 性能。在我看来,如果系统的上下文切换次数比较稳定,那么从数百到一万以内,都应该算是正常的。但当上下文切换次数超过一万次,或者切换次数出现数量级的增长时,就很可能已经出现了性能问题。

这时,你还需要根据上下文切换的类型,再做具体分析。比方说:

自愿上下文切换变多了,说明进程都在等待资源,有可能发生了 I/O 等其他问题;
    非自愿上下文切换变多了,说明进程都在被强制调度,也就是都在争抢 CPU,说明 CPU 的确成了瓶颈;
    中断次数变多了,说明 CPU 被中断处理程序占用,还需要通过查看 /proc/interrupts 文件来分析具体的中断类型。

小结

通过一个 sysbench 的案例,给你讲了上下文切换问题的分析思路。碰到上下文切换次数过多的问题时,我们可以借助 vmstat 、 pidstat 和 /proc/interrupts 等工具,来辅助排查性能问题的根源。

首先通过uptime查看系统负载,然后使用mpstat结合pidstat来初步判断到底是cpu计算量大还是进程争抢过大或者是io过多,接着使用vmstat分析切换次数,以及切换类型,来进一步判断到底是io过多导致问题还是进程争抢激烈导致问题。

原文地址:https://www.cnblogs.com/fadewalk/p/11179318.html

时间: 2024-10-09 13:04:46

2.2 CPU 上下文切换是什么意思?(下)的相关文章

cpu上下文切换(下)

cpu上下文切换如何查看 上一篇介绍了cpu上下文切换几种场景以及数据保存恢复过程,这篇文章介绍如何查看cpu上下文切换 一.vmstat 安装:yum install -y sysstat vmstat是一个常用的系统性能分析工具,主要用来分析系统的内存情况,也常用来分析cpu上下文切换和中断的次数. # vmstat <br/>procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----&l

CPU上下文切换(上)

CPU上下文切换 ? 我们经常说的平均负载和cpu升高没有直接的关系,在不同的场景cpu升高会导致系统负载,但是系统负载不一定是cpu升高导致的. 一.系统负载过高的三种场景 cpu密集型进程,使用大量cpu会导致平均负载升高,此时这两者是一致的. io密集型进程,等待io也会导致平均负载升高,但cpu不一定很高. 大量等待cpu的进程调度也会导致平均负载升高,此时cpu使用率也会比较高. ? 大量进程竞争cpu(也就是上面的第三个场景),往往是被忽略的,cpu虽然没有使用,只是在竞争,也会发生

Linux性能优化从入门到实战:03 CPU篇:CPU上下文切换

??linux操作系统是将CPU轮流分配给任务,分时执行的.而每次执行任务时,CPU需要知道CPU寄存器(CPU内置的内存)和程序计数器PC(CPU正在执行指令和下一条指令的位置)值,这些值是CPU执行任务所依赖的环境,也就是CPU上下文. ??CPU上下文切换,就是把前一个任务的CPU上下文(CPU寄存器和程序计数器)保存起来,然后加载入新任务的上下文到CPU寄存器和程序计数器中,最后跳转到程序计数器所指的位置,运行新任务. ??保存下来的上下文会在系统内核中,并在任务重新调度执行时再次加载进

CPU 上下文切换之理论篇(上)

1.什么是上下文?答:上下文是由CPU寄存器和程序计数器组成 2.CPU为什么进行上下文切换?答:CPU上下文切换,是保证Linux系统正常工作的核心功能之一 3.什么是CPU上下文切换?答:CPU上下文切换,就是先把前一个任务的CPU上下文保存起来,然后加载新任务的上下文到这些寄存器和程序计数器中,最后跳转到程序计数器所指的新位置,运行任务 4.什么是cpu寄存器?答:cpu寄存器是cpu内置很小.但速度极快的内存 5.什么是程序计数器?答:是用来存储CPU正在执行的指令位置.或者即将执行的下

03讲基础篇:经常说的CPU上下文切换是什么意思(上)

1.多任务竞争CPU,cpu变换任务的时候进行CPU上下文切换(context switch).CPU执行任务有4种方式:进程.线程.或者硬件通过触发信号导致中断的调用.2.当切换任务的时候,需要记录任务当前的状态和获取下一任务的信息和地址(指针),这就是上下文的内容.因此,上下文是指某一时间点CPU寄存器(CPU register)和程序计数器(PC)的内容, 广义上还包括内存中进程的虚拟地址映射信息.3.上下文切换的过程:(1)记录当前任务的上下文(即寄存器和计算器等所有的状态):(2)找到

03 | 基础篇:经常说的 CPU 上下文切换是什么意思?(上)

一.关于上下文切换的几个为什么 1.上下文切换是什么? 上下文切换是对任务当前运行状态的暂存和恢复 2.为什么CPU要进行上下文切换 当多个进程竞争CPU的时候,为了保证每个进程可以公平被CPU调用,采用处理任务按时间分片的机制,当某个时间片上的任务达到最后的时间点,那么这个任务就好被挂起,处理下一个任务,由于CPU处理的速度非常快,在人类感知上认为是并行处理的,实际是伪并行,同一时间只有一个任务在运行处理. 3.上下文切换主要消耗什么资源,为什么说上下文切换次数过多不可取? 浪费太多时间在切换

cpu上下文切换

cpu上下文就是寄存器和程序计数器.这里记录着指令的位置,他们存在系统内核 系统调用过程叫上下文切换. 进程的上下文切换,线程的上下文切换,中断的上下文切换 一:进程的上下文切换:他与系统调用的不同是,进程中还包括,虚拟内存,全部变量,栈等用户态.也包括寄存器,内核堆栈等内核态 二:线程的上下文切换,如何进程中只一个线程,那这个线程相当于线程 三:中断上下文切换:会打断正常的进程,优先级高 怎么查看系统上下文切换? 利用sysbench,vmstat,pidstat ,和 /proc/inter

Linux下如何查看高CPU占用率线程 LINUX CPU利用率计算

目录(?)[-] proc文件系统 proccpuinfo文件 procstat文件 procpidstat文件 procpidtasktidstat文件 系统中有关进程cpu使用率的常用命令 ps 命令 top命令 单核情况下Cpu使用率的计算 基本思想 总的Cpu使用率计算 计算方法 某一进程Cpu使用率的计算 计算方法 实验数据 某一线程Cpu使用率的计算 计算方法 实验数据 多核情况下cpu使用率的计算 实验一 描述 数据一 数据二 实验二 描述 数据一 数据二 主要问题 Java 系统

Linux环境下Java应用性能分析定位-CPU使用篇

1     CPU热点分析定位背景 CPU资源还是很昂贵的,为了深刻感受到这种昂贵,间下图当前CPU的资源售价: 所以对于程序猿们来说,需要让程序合理高效的使用CPU资源.利用有限的CPU资源来解决完成我们面对的实际问题,这就是为什么我们要尽可能优化程序. 不篇从微观层面展开介绍说明,不做宏观层面的介绍(譬如数据中心级容量监控,管理调度(OpenStack,Kubernates等)以及迁移(手动,自动,冷迁,热迁)). 本篇将以倒推式方法组织目录结构.出现了问题怎么办,以及为什么要这样做,以及后