• 【操作系统】聊聊CPU上下文切换实操


    如何查看系统的上下文切换情况

    上一篇文章我们说了过多的上下文切换,会把CPU时间消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢复上,那么当出现系统的上下文切换过多的时候,我们如果通过监控指标查看呢。

    vmstat 是一个常用的系统性能分析工具,主要用来分析系统的内存使用情况,也常用来分析 CPU 上下文切换和中断的次数。
    vmstat 5 代表的是5S输出一组

    root@qxlxi:/data# 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 1296640 195580 158788 2402740    0    1     3    23   22   46  0  0 99  0  0
     0  0 1296640 222836 158788 2402740    0    0     0    17   52   92  1  1 99  0  0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • cs(context switch)每秒上下文切换次数
    • in (interrupt) 每秒中断的次数
    • r (Running or Runnable) 是就绪队列的长度,也就是可运行的进程数(进行和等待)
    • b (Blocked) 处于不可中断睡眠状态的进程数

    从图中可以看到cs是92次上下文切换 in 52次中断。就绪队列和不可中断进程数都是0

    查看每个进程的数据,使用 pidstat -w

    root@qxlxi:/data# pidstat -w 5
    Linux 5.4.0-100-generic (qxlxi) 	09/23/2023 	_aarch64_	(2 CPU)
    
    12:45:26 PM   UID       PID   cswch/s nvcswch/s  Command
    12:45:31 PM     0         9      0.20      0.00  ksoftirqd/0
    12:45:31 PM     0        10      3.79      0.00  rcu_sched
    12:45:31 PM     0        11      0.20      0.00  migration/0
    12:45:31 PM     0        17      0.20      0.00  migration/1
    12:45:31 PM     0        18      0.40      0.00  ksoftirqd/1
    12:45:31 PM     0       365      0.80      0.00  kworker/0:1H-kblockd
    12:45:31 PM     0       382      0.20      0.00  kworker/1:1H-kblockd
    12:45:31 PM   118       876      1.80      0.00  avahi-daemon
    12:45:31 PM     0       885      0.20      0.00  irqbalance
    12:45:31 PM   128      1490      0.20      0.00  gsd-color
    12:45:31 PM  1000      1615      2.00      0.00  systemd
    12:45:31 PM  1000      1708      0.20      0.00  Xorg
    12:45:31 PM  1000      1888      0.20      0.00  gnome-shell
    12:45:31 PM  1000      2006      0.20      0.00  gsd-color
    12:45:31 PM     0     19788      0.20      0.00  systemd-journal
    12:45:31 PM     0     60439      1.00      0.00  multipathd
    12:45:31 PM     0     88948      4.19      1.60  systemd-udevd
    12:45:31 PM  1000    115630      0.20      0.00  gnome-control-c
    12:45:31 PM     0    487397      2.00      0.00  kworker/u4:1-events_power_efficient
    12:45:31 PM     0    488871      6.99      0.00  kworker/1:1-events
    12:45:31 PM     0    489061      0.40      0.00  kworker/u4:0-events_freezable_power_
    12:45:31 PM     0    489366      8.18      0.00  kworker/0:2-events
    12:45:31 PM     0    489376      0.20      0.00  pidstat
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • cswch/s : 每秒自愿上下文切换(voluntary context switches)的次数
    • nvcswch/s:每秒非自愿上下文切换 (non voluntary context switches) 的次数

    自愿上下文切换:进程获取不到自愿的时候,发生的上下文切换,比如IO、网络、内存资源不足的时候。
    非自愿上下文切换:进程执行时间到了,被系统强制调度,进而发生上下文切换,比如大量进程竞争CPU

    场景分析

    sysbench --threads=10 --max-time=300 threads run
    
    • 1

    模拟10个线程执行。

    查看总体

    root@qxlxi:/data# 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 1296640 222000 158804 2403064    0    1     3    23   23   21  0  0 99  0  0
    10  0 1296640 222000 158804 2403064    0    0     0    80 132863 2924643 15 80  5  0  0
     5  0 1296640 222000 158804 2403064    0    0     0     0 142952 2734656 14 81  5  0  0
     8  0 1296640 222000 158804 2403064    0    0     0     0 157159 2996906 14 85  1  0  0
     7  0 1296640 221968 158804 2403064    0    0     0     0 140886 2726608 13 78  9  0  0
     9  0 1296640 221968 158804 2403064    0    0     0     0 142394 2722918 14 80  6  0  0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    查看上下文切换次数升级到200多万,而就绪队列达到了10,us和sy的和达到了100%,sy的占用率80多,肯定有大量的CPU竞争。重点的次数也达到了1W多。

    综合分析,就绪队列过长,导致的大量进程上下文切换,从而导致系统CPU占用率更高。

    查看进程

    pidstat -w -u 1 查看进程上下文切换数据

    qxlxi@qxlxi:~$ pidstat -w -u 1
    Linux 5.4.0-100-generic (qxlxi) 	09/23/2023 	_aarch64_	(2 CPU)
    
    12:51:09 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
    12:51:10 PM  1000      1699    0.98    0.00    0.00    0.00    0.98     0  gvfs-afc-volume
    12:51:10 PM     0    489611   28.43  160.78    0.00    0.00  189.22     0  sysbench
    12:51:10 PM  1000    489646    0.00    0.98    0.00    0.00    0.98     1  pidstat
    
    12:51:09 PM   UID       PID   cswch/s nvcswch/s  Command
    12:51:10 PM     0        10      2.94      0.00  rcu_sched
    12:51:10 PM     0        18      0.98      0.00  ksoftirqd/1
    12:51:10 PM     0       382      0.98      0.00  kworker/1:1H-kblockd
    12:51:10 PM  1000      1615      1.96      0.00  systemd
    12:51:10 PM     0     60439      0.98      0.00  multipathd
    12:51:10 PM     0    487195      6.86      0.00  kworker/0:1-events
    12:51:10 PM     0    488871      5.88      0.00  kworker/1:1-events
    12:51:10 PM     0    489585      0.98      0.00  kworker/u4:2-events_freezable_power_
    12:51:10 PM  1000    489646      0.98     53.92  pidstat
    
    12:51:10 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
    12:51:11 PM   128      1420    1.00    0.00    0.00    0.00    1.00     0  gnome-shell
    12:51:11 PM     0    489611   26.00  161.00    0.00    0.00  187.00     0  sysbench
    
    12:51:10 PM   UID       PID   cswch/s nvcswch/s  Command
    12:51:11 PM     0        10      8.00      0.00  rcu_sched
    12:51:11 PM     0        18      3.00      0.00  ksoftirqd/1
    12:51:11 PM   128      1420      3.00     12.00  gnome-shell
    12:51:11 PM  1000      1615      2.00      0.00  systemd
    12:51:11 PM  1000      1888      3.00      8.00  gnome-shell
    12:51:11 PM     0     60439      1.00      0.00  multipathd
    12:51:11 PM     0    487195      7.00      0.00  kworker/0:1-events
    12:51:11 PM     0    487397     47.00      0.00  kworker/u4:1-events_unbound
    12:51:11 PM  1000    488358     10.00      0.00  sshd
    12:51:11 PM     0    488871      4.00      0.00  kworker/1:1-events
    12:51:11 PM     0    489585    206.00      0.00  kworker/u4:2-events_unbound
    12:51:11 PM  1000    489646      1.00    253.00  pidstat
    
    12:51:11 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
    12:51:12 PM     0    489611   19.00  169.00    0.00    0.00  188.00     0  sysbench
    12:51:12 PM  1000    489646    0.00    1.00    0.00    1.00    1.00     1  pidstat
    
    12:51:11 PM   UID       PID   cswch/s nvcswch/s  Command
    12:51:12 PM     0        10      4.00      0.00  rcu_sched
    12:51:12 PM     0        18     10.00      0.00  ksoftirqd/1
    12:51:12 PM  1000      1615      2.00      0.00  systemd
    12:51:12 PM  1000      2130      1.00      0.00  evolution-alarm
    12:51:12 PM     0     60439      1.00      0.00  multipathd
    12:51:12 PM     0    487195      4.00      0.00  kworker/0:1-events
    12:51:12 PM     0    487397    165.00      0.00  kworker/u4:1-events_unbound
    12:51:12 PM  1000    488358     18.00      0.00  sshd
    12:51:12 PM     0    488871      5.00      0.00  kworker/1:1-events
    12:51:12 PM     0    489585    113.00      0.00  kworker/u4:2-events_freezable_power_
    12:51:12 PM  1000    489646      1.00    289.00  pidstat
    
    12:51:12 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
    12:51:13 PM     0    489611   27.00  158.00    0.00    0.00  185.00     0  sysbench
    
    12:51:12 PM   UID       PID   cswch/s nvcswch/s  Command
    12:51:13 PM     0        10      5.00      0.00  rcu_sched
    12:51:13 PM     0        11      1.00      0.00  migration/0
    12:51:13 PM     0        17      1.00      0.00  migration/1
    12:51:13 PM     0        18      1.00      0.00  ksoftirqd/1
    12:51:13 PM  1000      1615      2.00      0.00  systemd
    12:51:13 PM     0     60439      1.00      0.00  multipathd
    12:51:13 PM     0    487195      8.00      0.00  kworker/0:1-events
    12:51:13 PM     0    487397     96.00      0.00  kworker/u4:1-flush-253:0
    12:51:13 PM  1000    488358     15.00      0.00  sshd
    12:51:13 PM     0    488871      5.00      0.00  kworker/1:1-events
    12:51:13 PM     0    489585    165.00      0.00  kworker/u4:2-events_unbound
    12:51:13 PM  1000    489646      1.00    258.00  pidstat
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    从图中可以发现,切换较多的自愿上下文切换是进程 kworker/u4:2-events_unbound,而这里只是显示的是进程的上下文切换,而CPU在运行的是时候, Linux 调度的基本单位实际上是线程

    pidstat -wt 1  可以查看线程的指标
    
    1:06:41 PM   UID      TGID       TID   cswch/s nvcswch/s  Command
    01:06:43 PM     0         1         -      0.92      0.00  systemd
    01:06:43 PM     0         -         1      0.92      0.00  |__systemd
    01:06:43 PM     0        10         -     19.27      0.00  rcu_sched
    01:06:43 PM     0         -        10     19.27      0.00  |__rcu_sched
    01:06:43 PM     0        18         -      8.26      0.00  ksoftirqd/1
    01:06:43 PM     0         -        18      8.26      0.00  |__ksoftirqd/1
    01:06:43 PM     0       382         -      0.92      0.00  kworker/1:1H-kblockd
    01:06:43 PM     0         -       382      0.92      0.00  |__kworker/1:1H-kblockd
    01:06:43 PM     0         -       937      0.92      0.00  |__gmain
    01:06:43 PM   128         -      1300      0.92      0.00  |__gvfs-afc-volume
    01:06:43 PM   128         -      1422      0.92      0.00  |__gmain
    01:06:43 PM  1000      1615         -      1.83      0.00  systemd
    01:06:43 PM  1000         -      1615      1.83      0.00  |__systemd
    01:06:43 PM  1000         -      1700      0.92      0.00  |__gvfs-afc-volume
    01:06:43 PM  1000      1708         -      3.67      0.00  Xorg
    01:06:43 PM  1000         -      1708      3.67      0.00  |__Xorg
    01:06:43 PM  1000      1888         -      2.75      0.00  gnome-shell
    01:06:43 PM  1000         -      1888      2.75      0.00  |__gnome-shell
    01:06:43 PM  1000         -      1900      0.92      0.00  |__gmain
    01:06:43 PM  1000         -      2336      0.92      0.00  |__gmain
    01:06:43 PM  1000         -      2745      0.92      0.00  |__gmain
    01:06:43 PM     0         -     56981      0.92      0.00  |__gmain
    01:06:43 PM     0     60439         -      0.92      0.00  multipathd
    01:06:43 PM     0         -     60439      0.92      0.00  |__multipathd
    01:06:43 PM     0         -     60443      0.92      0.00  |__multipathd
    01:06:43 PM     0    487397         -      0.92      0.00  kworker/u4:1-events_freezable_power_
    01:06:43 PM     0         -    487397      0.92      0.00  |__kworker/u4:1-events_freezable_power_
    01:06:43 PM  1000    489904         -      1.83      0.00  baobab
    01:06:43 PM  1000         -    489904      1.83      0.00  |__baobab
    01:06:43 PM     0    490271         -      7.34      0.00  kworker/0:2-events
    01:06:43 PM     0         -    490271      7.34      0.00  |__kworker/0:2-events
    01:06:43 PM     0    490366         -      3.67      0.00  kworker/1:3-events
    01:06:43 PM     0         -    490366      3.67      0.00  |__kworker/1:3-events
    01:06:43 PM     0         -    490582  37280.73 249111.93  |__sysbench
    01:06:43 PM     0         -    490583  30613.76 227590.83  |__sysbench
    01:06:43 PM     0         -    490584  42267.89 214733.03  |__sysbench
    01:06:43 PM     0         -    490585  36483.49 247768.81  |__sysbench
    01:06:43 PM     0         -    490586  35252.29 251989.91  |__sysbench
    01:06:43 PM     0         -    490587  35150.46 240639.45  |__sysbench
    01:06:43 PM     0         -    490588  33030.28 207896.33  |__sysbench
    01:06:43 PM     0         -    490589  34731.19 233100.00  |__sysbench
    01:06:43 PM     0         -    490590  39934.86 232202.75  |__sysbench
    01:06:43 PM     0         -    490591  36001.83 261024.77  |__sysbench
    01:06:43 PM     0    490592         -      0.92   2479.82  pidstat
    01:06:43 PM     0         -    490592      0.92   2502.75  |__pidstat
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    到此,我们就分析出,上下文切换过多的进程是kworker。但是还有一个中断次数过多的问题。

    因为中断是发生在内核中的,所以我们需要通过/proc中的信息进行查看。

    watch -d cat /proc/interrupts 
    
    • 1

    小结

    本篇主要介绍了查看上下文切换的几个常用命令,分别是

    vmstat 5 //总体监控
    pidstat -w 5 //进程监控
    pidstat -w -u 1 //-w 参数表示输出进程切换指标,而 -u 参数则表示输出 CPU 使用指标
    pidstat -wt 1 // -wt 参数表示输出线程的上下文切换指标
    watch -d cat /proc/interrupts //内核中断指标
    
    • 1
    • 2
    • 3
    • 4
    • 5

    而自愿上下文切换边多,说明进程在等待资源,可能发生了IO问题
    非自愿上下文切换过多,说明进程在被强制调度,争抢CP
    中断次数过多,说明CPU被中断程序占用

  • 相关阅读:
    自定义类型详解(上)
    Three.js-效果合成(EffectComposer)
    二、PyTorch加载数据
    Lingolingo
    SPI通信
    centOS7安装rabbitMQ
    Java SE 16 新增特性
    Java 面试题
    React 图片展示组件
    ES6 Set数据结构
  • 原文地址:https://blog.csdn.net/jia970426/article/details/133217177