CPU上下文切换可分为进程上下文切换、线程上下文切换和中断上下文切换。

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

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

查看进程上下文切换情况

#每5s输出一组数据
# 每隔5秒输出1组数据
$ pidstat -w 5
Linux 4.15.0 (ubuntu)  09/23/18  _x86_64_  (2 CPU)

08:18:26      UID       PID   cswch/s nvcswch/s  Command
08:18:31        0         1      0.20      0.00  systemd
08:18:31        0         8      5.40      0.00  rcu_sched
...
pidstat -w -u 1
pidstat -wt 1

系统的就绪队列过长,也就是正在运行和等待CPU的进程数过多,会导致大量的上下文切换,而上下文切换会导致系统CPU占用率升高。

自愿上下文切换和非自愿上下文切换

  • 自愿上下文切换,是指进程无法获取所需资源,导致的上下文切换。比如说,IO、内存等系统资源不足时,就会发生自愿上下文切换。

  • 非自愿上下文切换,则是指进程由于时间片已等到等原因,被系统强制调度,进而发生的上下文切换。比如说,大量进程都在争抢CPU时,就容易发生非自愿上下文切换。

每次上下文切换多少次才算正常呢?

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

中断

watch -d cat /proc/interrupts

观察一段时间,可以发现,变化速度最快的是重调度中断(RES),这个中断类型表示,唤醒空间状态的CPU来调度新的任务运行。这是多处理器系统(SMP)中,调度器用来分散任务到不同CPU的机制,通常也被称为处理器间中断(IPI)。

小结

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

练习

# 以10个线程运行5分钟的基准测试,模拟多线程切换的问题
$ sysbench --threads=10 --max-time=300 threads run
vmstat 1
ps -ef|grep sysbench
pidstat -wt -p pid 1 5
watch -d cat /proc/interrupts