三. 性能优化之基础篇: 经常说的 CPU 上下文切换是什么意思?(下)

文章目录

    • 重要的上下文切换概念
        • 自愿上下文切换
        • 非自愿上下文切换
    • 工具
        • vmstat
        • pidstat
        • sysbench
        • /proc/interrupts
    • 案例
        • 多线程调度
    • 总结
    • tips

重要的上下文切换概念

自愿上下文切换

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

非自愿上下文切换

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

工具

vmstat

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

pidstat

  • 选项
-w 显示每个进程的上下文切换情况
-t 输出线程的指标
# 每隔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
...
  • 相关输出解析:
  1. cswch ,表示每秒自愿上下文切换(voluntary context switches)的次数
  2. nvcswch ,表示每秒非自愿上下文切换(non voluntary context switches)的次数。

sysbench

  1. 模拟系统多线程调度
#以10个线程运行5分钟的基准测试,模拟多线程切换的问题
$ sysbench --threads=10 --max-time=300 threads run

/proc/interrupts

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

  • 使用watch -d 监控/proc/interrupts文件
# -d 参数表示高亮显示变化的区域
$ watch -d cat /proc/interrupts
           CPU0       CPU1
...
RES:    2450431    5279697   Rescheduling interrupts
...

重调度中断(RES)个中断类型表示,唤醒空闲状态的 CPU 来调度新的任务运行,通常也被称为处理器间中断(Inter-Processor Interrupts,IPI)

案例

多线程调度

  1. 模拟多线程
# 以10个线程运行5分钟的基准测试,模拟多线程切换的问题
$ sysbench --threads=10 --max-time=300 threads run
  1. 查看上下文切换变化
#每隔1秒输出1组数据(需要Ctrl+C才结束)
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
  0      0 930152  65228 756172    0    0     4     0  125  226  0  1 99  0  0
 0  0      0 930168  65232 756232    0    0    48     0   80  151  0  0 100  0  0
 0  0      0 930168  65236 756216    0    0     8     0  109  210  0  0 100  0  0
 0  0      0 929988  65240 756220    0    0     4     0  113  216  0  0 100  0  0
 0  0      0 930028  65248 756224    0    0    12     0  111  205  1  1 97  1  0
0  0      0 930044  65260 756228    0    0    12    12  130  240  0  0 100  0  0
 8  0      0 925256  65264 759696    0    0  3452     0  201 26820  4  3 85  8  0
 9  0      0 924388  65268 759680    0    0     4   272 1119 1579178  6 94  0  0  0
 9  0      0 924248  65272 759708    0    0    32     0 1091 1581345  7 93  0  0  0

从一开始的100-250上下文切换数,到模拟后的百万级.切换数极数上升

  1. 追踪具体进程
# 每隔1秒输出一组数据(需要 Ctrl+C 才结束)
# -wt 参数表示输出线程的上下文切换指标
$ pidstat -wt 1
08:14:05      UID      TGID       TID   cswch/s nvcswch/s  Command
...
08:14:05        0     10551         -      6.00      0.00  sysbench
08:14:05        0         -     10551      6.00      0.00  |__sysbench
08:14:05        0         -     10552  18911.00 103740.00  |__sysbench
08:14:05        0         -     10553  18915.00 100955.00  |__sysbench
08:14:05        0         -     10554  18827.00 103954.00  |__sysbench
...
  1. 判断终端类型
# -d 参数表示高亮显示变化的区域
$ watch -d cat /proc/interrupts
           CPU0       CPU1
...
RES:    2450431    5279697   Rescheduling interrupts
...

总结

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

tips

  • stress和sysbench两个工具在压测过程中的对比发现:
  1. stress基于多进程的,会fork多个进程,导致进程上下文切换,导致us开销很高;
    sysbench基于多线程的,会创建多个线程,单一进程基于内核线程切换,导致sy的内核开销很高;

你可能感兴趣的:(笔记,性能优化,性能优化,Linux性能优化,cpu性能优化,上下文切换)