在本文中,我将进一步讨论如何分析CPU上下文切换问题。考察CPU上下文切换我们知道,过多的上下文切换会消耗CPU时间保存和恢复寄存器、程序计数器、内核堆栈和虚拟内存等数据,导致系统性能显着下降。既然上下文切换对系统性能的影响如此之大,那么我们如何检查呢?那么,您可以使用vmstat工具来查询系统的上下文切换。vmstatvmstat是一个常用的系统性能分析工具。主要用来分析内存使用情况,也常用于分析CPU上下文切换次数和中断次数。例如vmstat5(5秒输出间隔):我们看一下输出:cs(contextswitch):每秒的上下文切换次数。in(interrupt):每秒的中断次数。r(running|runnable):就绪队列的长度,即正在运行并等待CPU的进程数。b(blocked):处于不可中断睡眠状态的进程数。在上面的例子中,我们可以看到上下文切换的次数是33次,系统中断的次数是25次,就绪队列的长度,未中断状态的进程数都是0。pidstatvmstat工具只给出了关于系统的整体上下文切换。要查看每个进程的详细信息,您需要使用pidstat。添加-w选项,您可以看到每个进程的上下文切换:例如:$pidstat-w5Linux4.15.0(ubuntu)09/23/18_x86_64_(2CPUs)08:18:26UIDPIDcswch/snvcswch/sCommand08:18:31010.200.00systemd08:18:31085.400.00rcu_sched...结果中有两列需要我们注意:cswch和nvcswch。其中,cswch表示每秒自愿上下文切换次数,nvcswch表示每秒非自愿上下文切换次数。自愿上下文切换:指进程无法获取所需资源而引起的上下文切换。例如,当I/O和内存等系统资源不足时,会发生自愿上下文切换。Involuntarycontextswitch:指进程因为时间片过期而被系统强制重新调度时发生的上下文切换。例如,当大量进程竞争CPU时,很容易发生非自愿的上下文切换。您必须牢记这两个概念,因为它们意味着不同的性能问题。案例研究现在您知道如何查看这些指标,另一个问题出现了,上下文切换的频率是多少?让我们看一个例子。我们将使用sysbench,一种多线程基准测试工具,通过生成负载来模拟过度上下文切换的问题。假定您已经在Linux系统上安装了sysbench和sysstat。在我们模拟负载之前,让我们在终端中运行vmstat:这里我们可以看到当前上下文切换次数cs为35,中断次数in为19,r和b均为0。由于我目前没有其他任务在运行,它们是空闲系统中的上下文切换次数。现在让我们运行sysbench来模拟多线程调度系统的瓶颈:$sysbench--threads=10--max-time=300threadsrun现在,你应该看到vmstat输出与上面不同的结果:应该找到cs的酒吧的上下文切换次数从35次增加到139万次。同时注意其他几个指标:r:就绪队列长度已经达到8us和sy:us和sy的CPU占用率一起为100%,系统CPU占用率为84%,说明即CPU主要被内核占用。in:中断数也上升到10000个,说明中断处理也是一个潜在的问题。结合这些指标,我们可以知道系统的就绪队列过长,即等待CPU的进程运行过多,导致大量的上下文切换,大量的上下文切换导致增加在系统的CPU使用率。那么是什么过程导致了这些问题呢?我们继续分析,在第三个终端使用pidstat查看CPU和进程上下文切换:$pidstat-w-u108:06:33UIDPID%usr%system%guest%wait%CPUCPUCommand08:06:3401048830.00100.000.000.000.00100.000SYSBENCH08:06:340263260.000.000.000.000.0001.000KWORKER/U4:208:06:06:33UIDPIDCSWCH/SNVCSWCH/SNVCSWCH/SNVCSWCH/S命令08:06:06:06:340811.00RCU_SCHADD:34:34:34:34:34:34:34:34:34:34:34:34:34:34:34:34161.000.00ksoftirqd/108:06:3404711.000.00hv_balloon08:06:34012301.000.00iscsid08:06:34040891.000.00kworker/1:50310.030.030.03kworker/0:03kworker/1.00224.00pidstat08:06:34026326236.000.00kworker/u4:208:06:34100026784223.000.00sshd从pidstat的输出可以发现CPU占用率的上升确实是sysbench引起的,它的CPU占用率已经达到100%但是上下文切换来自其他进程,包括非自愿上下文切换频率最高的pidstat,以及自愿上下文切换频率最高的内核线程kworker和sshd。注意:默认情况下,pidstat只显示进程的上下文切换,如果要查看实际线程的上下文切换,请添加-t选项。中断要找出中断数量也很高的原因,您可以检查/proc/interrupts文件。这个文件提供了一个只读的中断用法。$watch-dcat/proc/interruptsCPU0CPU1...RES:24504315279697Reschedulinginterrupts...观察一段时间后,可以发现变化最快的是重调度中断(RES,RESchedulinginterrupt)。这种中断类型表示一个空闲的CPU被唤醒来安排一个新的任务运行。所以这里的中断增加是因为任务调度问题太多了,这和前面分析上下文切换次数是一致的。现在回到最初的问题,每秒多少次上下文切换才算正常?这个值其实取决于系统本身的CPU性能。在我看来,如果系统的上下文切换次数比较稳定的话,几百到一万应该是正常的。但是,当上下文切换次数超过10000次,或者切换次数快速增加时,很可能会出现性能问题。结论至此,您应该可以根据上下文切换的类型进行一些具体的分析。主动上下文切换较多,说明进程正在等待资源,可能会出现I/O饱和等其他问题。有很多不自觉的上下文切换,说明进程在被强制调度,也就是都在争CPU,说明CPU确实造成了瓶颈。中断次数增多说明CPU被中断处理程序占用,需要通过查看/proc/interrupts文件分析具体的中断类型。
