cpu上下文切换(下)

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

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

查看,使用vmstat,来查看系统的上下文切换

-vmstat是一个常用的系统性能分析工具,主要用来分析系统的内存使用情况,也常用来分析cpu上下文切换和中断的次数

#每隔5秒输出1组数据

[root@rac2 ~]# 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  55480 119220  14584 1101100    0    0    46    59  100  176  2  1 96  1  0

 2  0  55480 118700  14592 1101200    0    0    65    52 5235 4613  7  1 91  0  0

 0  0  55480 132024  14600 1101200    0    0    39    51 5147 4462  1  1 97  1  0

 0  0  55480 132060  14624 1101184    0    0    52   195 4501 4355  1  1 97  1  0

 --cs(context switch) 每秒上下文切换的次数

 --in(interrupt)每秒中断的次数

 --r(Running or Runnable)就绪队列的长度,也就是正在运行和等待cpu的进程数

 --b(blocked)处于不可中断睡眠状态的进程数

 这个例子中,上下文切换次数cs4613,而系统的中断次数是5235,就绪队列长度r2,不可中断进程b0

--vmstat只给出了 系统总体的上下文切换情况,想要查看每个进程的详细情况,叫使用pidstat,加上-w选项,可以看到每个进程上下文切换。

 #每隔5秒输出1组数据

 [root@rac2 ~]# pidstat -w 5  ##oracle

Linux 2.6.32-431.el6.x86_64 (rac2) 12/11/2018 _x86_64_ (2 CPU)

03:28:35 AM       PID   cswch/s nvcswch/s  Command

03:28:40 AM         3      0.20      0.00  migration/0

03:28:40 AM         4      5.00      0.00  ksoftirqd/0

[root@mysqlhq ~]# pidstat -w 5 ##mysql

Linux 3.10.0-514.ky3.kb3.x86_64 (mysqlhq) 12/11/2018 _x86_64_ (1 CPU)

11:29:14 AM   UID       PID   cswch/s nvcswch/s  Command

11:29:19 AM     0         1      0.40      0.00  systemd

11:29:19 AM     0         2      0.20      0.00  kthreadd

11:29:19 AM     0         3      2.19      0.00  ksoftirqd/0

11:29:19 AM     0         9     14.54      0.00  rcu_sched

关注对象:cswh表示每秒自愿上下文切换的次数,nvcswch 每秒非自愿上下文切换的次数。

这两个意味着不同的性能问题:

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

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

--案例分析

将使用sysbench来模拟系统多线程调度切换的情况

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

--install sysstat , sysbench

先查看vmstat--这个服务器已经运行了zabbix_server,zabbix_agentmysql server

[root@mysqlhq ~]# 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

 3  0   4020 9954628    456 4689728    0    0     1    98    4    0  0  0 99  0  0

 0  0   4020 9954412    456 4689736    0    0     1    20  140  240  1  1 99  0  0

 0  0   4020 9954288    456 4689740    0    0     1    24  140  235  0  1 99  0  0

操作和分析

CMD1首先运行sysbench

#10个线程运行5分钟的基准测试,模拟多线程切换的问题

[root@mysqlhq bin]#  ./sysbench  --test=threads --num-threads=10 --max-time=300  --max-requests=10000000 run

sysbench 0.5:  multi-threaded system evaluation benchmark

Running the test with following options:

Number of threads: 10

Random number generator seed is 0 and will be ignored

Threads started!

General statistics:

    total time:                          300.0033s

    total number of events:              541076

    total time taken by event execution: 2999.8114s

    response time:

         min:                                  0.62ms

         avg:                                  5.54ms

         max:                                184.57ms

         approx.  95 percentile:              12.58ms

Threads fairness:

    events (avg/stddev):           54107.6000/358.76

    execution time (avg/stddev):   299.9811/0.00

CMD2 运行vmstat,观察上下文切换

#每隔1秒输出1组数据

[root@mysqlhq ~]# 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

10  0   4020 9912476    456 4731980    0    0     0    15 1076 2227794 11 89  0  0  0

 9  0   4020 9912476    456 4731984    0    0     0    33 1074 2106294 10 90  0  0  0

 8  0   4020 9912476    456 4731988    0    0     4    20 1086 2201340 11 89  0  0  0

 8  0   4020 9912476    456 4731988    0    0     0    21 1083 2180260 11 89  0  0  0

 8  0   4020 9912476    456 4731988    0    0     0    15 1088 2190698 10 90  0  0  0

 7  0   4020 9912416    456 4732032    0    0     0    21 1093 2147982 10 90  0  0  0

 8  0   4020 9912476    456 4731992    0    0     0    24 1066 2200320  9 91  0  0  0

可以发现,cs列的上下文切换从140变成200多万(2227794)同时其他几个指标:

--r列,就绪队列的长度已经到8,远超过了系统cpu的个数1,所以肯定会有大量的cpu竞争

--uruser)和sysystem)列,这两列的cpu使用率加起来上升到100%,其中系统cpu的使用率,sy也是90%,说明cpu主要被内核占用

--in列,中断次数上午到1千多,说明中断处理也是个潜在的问题

我们继续分析pidstat

CMD3 开启pidstat分析

#每隔1秒输出一组数据

#-w参数表示输出进程切换指标,-u表示输出cpu指标

[root@mysqlhq ~]# pidstat -w -u 1

Linux 3.10.0-514.ky3.kb3.x86_64 (mysqlhq) 12/11/2018 _x86_64_ (1 CPU)

02:52:21 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command

02:52:22 PM     0      4566   10.00   89.00    0.00    0.00   99.00     0  sysbench

02:52:22 PM     0      4615    1.00    0.00    0.00    0.00    1.00     0  pidstat

02:52:21 PM   UID       PID   cswch/s nvcswch/s  Command

02:52:22 PM     0         3      1.00      0.00  ksoftirqd/0

02:52:22 PM     0         9     16.00      0.00  rcu_sched

02:52:22 PM     0       401     20.00      0.00  xfsaild/dm-0

02:52:22 PM     0       641      6.00      0.00  rngd

02:52:22 PM     0       654     10.00      0.00  vmtoolsd

02:52:22 PM     0       948      1.00      0.00  httpd

02:52:22 PM     0      4433      3.00      0.00  kworker/u2:2

02:52:22 PM     0      4603      1.00      0.00  vmstat

02:52:22 PM     0      4615      1.00      0.00  pidstat

02:52:22 PM     0     13189      1.00      0.00  sshd

02:52:22 PM  1001     14930      1.00      0.00  zabbix_server

从上面的输出可以发现,cpu使用率的升高是有sysbench导致,它是cpu的使用率达到99%

但上下文进程来自其他进程,包括非自愿上下文切换(nvcswch)频率都不高,以及自愿上下文切换(cswch)频率最高的内核线程xfsaildrcu_sched

在第三个cmd运行

#每隔1秒输出一组数据

#-wt参数表示输出线程的上下文切换指标

[root@mysqlhq ~]# pidstat -wt 1

Linux 3.10.0-514.ky3.kb3.x86_64 (mysqlhq) 12/11/2018 _x86_64_ (1 CPU)

02:52:42 PM   UID      TGID       TID   cswch/s nvcswch/s  Command

02:52:45 PM     0         1         -      0.56      0.00  systemd

02:52:45 PM     0         -         1      0.56      0.00  |__systemd

02:52:45 PM     0         3         -      1.67      0.00  ksoftirqd/0

Average:        0         -      4567  18732.02  99320.39  |__sysbench

Average:        0         -      4568  18726.12  97318.25  |__sysbench

Average:        0         -      4569  18039.89  99486.76  |__sysbench

Average:        0         -      4570  22523.79  93687.48  |__sysbench

Average:        0         -      4571  17065.83 104014.13  |__sysbench

Average:        0         -      4572  13025.04 105903.40  |__sysbench

Average:        0         -      4573  15888.55 101816.82  |__sysbench

Average:        0         -      4574  22786.76  96230.59  |__sysbench

Average:        0         -      4575  17305.01  98868.69  |__sysbench

Average:        0         -      4576  15172.99 102271.91  |__sysbench

现在看到,虽然sysbench进程(主线程)的上下文切换看起来并不多,但是它的子线程的上下文切换却有很多,这样,切换最多的还是sysbench线程

观察了前面的指标,除了上下文切换,还有中断也上升,pidstat只是一个性能分析工具,并不提供任何关于中断的详细信息,要想知道中断发生,使用/proc/interrupts这个文件中读取,/proc实际上是linux的一个虚拟文件系统,用于内核空间与用户空间之间的通信,/proc/interrupts就是这种通信机制的一部分,提供了一个只读的中断使用情况

#-d 表示高亮显示变化的区域

[root@mysqlhq ~]# watch -d cat /proc/interrupts

 56:  206883607   PCI-MSI-edge      ens160-rxtx-0

 57:          0   PCI-MSI-edge      ens160-event-1

 58:         29   PCI-MSI-edge      vmw_vmci

 59:          0   PCI-MSI-edge      vmw_vmci

NMI:          0   Non-maskable interrupts

LOC:  518628350   Local timer interrupts

SPU:          0   Spurious interrupts

PMI:          0   Performance monitoring interrupts

IWI:   27023118   IRQ work interrupts

RTR:          0   APIC ICR read retries

RES:          0   Rescheduling interrupts

CAL:          0   Function call interrupts

TLB:          0   TLB shootdowns

TRM:          0   Thermal event interrupts

重调度中断(RES),这个中断类型表示,唤醒空闲状态的cpu来调度新的任务运行。(由于这里只有1cpu,所以看不出变化),在多处理器系统(SMP)中,调度器来分散任务不同cpu的机制,通常也被称为处理器中断(IPI

--在多cpu的环境

==

NMI:          0          0   Non-maskable interrupts

LOC:  195410914  299299647   Local timer interrupts

SPU:          0          0   Spurious interrupts

PMI:          0          0   Performance monitoring interrupts

IWI:          0          0   IRQ work interrupts

RES:   13385697   13410503   Rescheduling interrupts

CAL:        170     581892   Function call interrupts

TLB:    1011141    1058822   TLB shootdowns

TRM:          0          0   Thermal event interrupts

THR:          0          0   Threshold APIC interrupts

MCE:          0          0   Machine check exceptions

通过这个案例,用pidstat观测,有很严重的上下文切换,每秒到底多少的上下文切换才是正常的呢

这个数值其实取决于系统本身的cpu性能,如果系统的上下文切换次数比较稳定,那么在百万以内,都算是正常的。但当上下文切换次数超过一百万次,或者切换次数出现数量级的增长时,就可能已经出现了性能问题。这时,需要根据上下文切换的类型,再具体分析

--自愿上下文切换变多,说明进程都在等待资源,有可能发生了io等其他问题。

--非自愿切换变多,说明进程都在备强制调度,也就是在争抢cpu,说明cpu成了瓶颈

--中断次数变多了,说明cpu被中断处理程序占用,还需要查看/proc/interrupts文件类分析具体的中断类型

--小结

使用sysbench案例,讲了上下文切换问题的分析思路。碰到上下文切换次数过多的问题, 可以借助vmstat,pidstat,/proc/interrupts等工具,来辅助分析问题。

猜你喜欢

转载自www.cnblogs.com/yhq1314/p/10102660.html