0
点赞
收藏
分享

微信扫一扫

Linux性能优化实战学习笔记三

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

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

既然上下文切换对系统性能影响那么大,到底要怎么查看上下文切换呢?我们可以通过vmstat来查询系统的上下文切换情况。

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

比如:

# 每隔5秒输出1组数据
#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
 1  0      0 14240388 162080 1381008    0    0     0     2    25    33  0  0 100  0  0

每一列含义可参考:https://blog.csdn.net/wgq2020/article/details/134094555。我这里重点强调下以下四列内容:

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

可以看到,这个例子中上下文切换次数cs是33次,而系统中断次数in是25次,而就绪队列长度r和不可中断状态进程数b都是0。

vmstat只给出了系统总体的上下文切换情况,想要查看每个进程的详细情况,就需要使用我们前面提到过的pidstat了。给它加上-w选项,你就可以查看每个进程上下文切换情况了

#每隔5秒输出1组数据
 #pidstat -w 5
Linux 3.10.0-1160.92.1.el7.x86_64 (ensp-nginx)  04/10/2024      _x86_64_        (8 CPU)

03:53:09 PM   UID       PID   cswch/s nvcswch/s  Command
03:53:14 PM     0         9      9.60      0.00  rcu_sched
03:53:14 PM     0        11      0.20      0.00  watchdog/0
03:53:14 PM     0        12      0.20      0.00  watchdog/1
...

cswch表示每秒自愿上下文切换(voluntary context switches)的次数
nvcswch表示每秒非自愿上下文切换(non voluntary context switches)的次数
这两个概念一定要记住,因为他们意味着不同的性能问题:
1.所谓自愿上下文切换,是指进程无法获取 所需资源,导致的上下文切换。
  比如,I/O、内存等系统资源不足时,就会发生自愿上下文切换。
2.而非自愿上下文切换,则是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。
  比如说,大量进程都在争抢CPU时,就容易发生非自愿上下文切换。

案例分析

一、环境与测试工具准备

1、操作系统

[root@ensp-nginx ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)

2、测试工具

yum install sysbench sysstat -y

3、机器配置

#grep 'model name' /proc/cpuinfo |wc -l     #cpu
8
# grep 'MemTotal' /proc/meminfo 
MemTotal:       16264988 kB                 #内存

二、操作和分析

首先,在第一个终端运行sysbench,模拟系统多线程调度瓶颈:

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

第二个终端运行vmstat,观察上下文切换情况

# 每隔1秒输出1组数据,需要ctrl+c才结束
#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
11  0      0 14226056 162236 1388140    0    0     0     0 170307 818244 16 84 37  0  0
 9  0      0 14226056 162236 1388140    0    0     0     0 167015 815787 16 84 37  0  0

你应该可以发现,cs列的上下文切换次数骤然上升到了81万。同时注意观察其他几个指标:

r列:就绪队列的长度已经到了11,所以肯定会有CPU竞争。

us(user)和sy(system)列:这2列的CPU使用率加起来上升到了100%,其中系统CPU使用率,也就是sy列高达84%,说明CPU主要时被内核占用了。

in列:中断次数也上升到17万,说明中断处理也是问题。

# 每隔1秒输出一组数据    -w参数表示输出进程切换指标  -u表示输出CPU使用指标
#pidstat -w -u 1
Linux 3.10.0-1160.92.1.el7.x86_64 (ensp-nginx)  04/11/2024      _x86_64_        (8 CPU)
...
10:45:17 AM   UID      TGID       TID    %usr %system  %guest    %CPU   CPU  Command
10:45:18 AM     0     21746         -  116.00  491.00    0.00  607.00     2  sysbench
10:45:18 AM     0         -     21747    8.00   24.00    0.00   32.00     1  |__sysbench
10:45:18 AM     0         -     21748    5.00   23.00    0.00   28.00     7  |__sysbench
10:45:18 AM     0         -     21749    5.00   25.00    0.00   30.00     1  |__sysbench
10:45:18 AM     0         -     21750    4.00   24.00    0.00   28.00     5  |__sysbench
...

从pidstat的输出可以发现,CPU使用率升高果然时sysbench导致的,它的CPU使用率高达600%。

#-wt参数表示输出线程的上下文切换指标
#pidstat -wt 1
10:34:44 AM   UID      TGID       TID   cswch/s nvcswch/s  Command
...
10:34:45 AM     0         21747         -      3.96      0.00  sysbench
10:45:18 AM     0         -     21747  21724.00   7354.00  |__sysbench
10:45:18 AM     0         -     21748  22547.00   6817.00  |__sysbench
10:45:18 AM     0         -     21749  22197.00   6954.00  |__sysbench
10:45:18 AM     0         -     21750  22635.00   6891.00  |__sysbench
10:45:18 AM     0         -     21751  21860.00   7123.00  |__sysbench
...

你应该能看到,虽然sysbench进程(也就是主线程)的上下文切换次数并不多,但它的子线程的上下文切换次数却很多。看来上下文切换罪魁祸首,还是过多的sysbench线程。

那是不是到这里就可以结束了呢?

当然不是。前面观察系统指标时,除了上下文切换频率升高,中断次数也上升到了17万,但是到底什么导致的中断次数上升,我们还不清楚。

既然是中断,我们都知道,它只发生在内核态,而pidstat只是一个进程的性能分析工具,并不提供任何关于中断的信息,怎么才能知道中断发生的类型呢?

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

第三个终端里,运行如下:

# -d 参数表示高亮显示变化的区域
# watch -d cat /proc/interrupts
           CPU0       CPU1       CPU2       CPU3       CPU4       CPU5       CPU6       CPU7
...
RES:   73755215   55944503   68991624   55527260   71992122   55675436   71387076   55803899   Rescheduling interrupts
...

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

所以,这里的中断升高还是因为过多的任务的调度问题,跟前面上下文切换次数的分析结果是一致的。

通过这个案例,你应该也发现了多工具、多方面指标对比观测的好处。如果最开始,我们只用了pidstat观测,这些很严重的上下文切换线程,压根就发现不了。

现在再回到最初的问题,每秒上下文切换多少次才算正常呢?

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

这时,你还需要根据上下文切换的类型,再分析:

1. 自愿上下文切换变多了,说明进程都在等待资源,有可能发生了I/O等其他问题

2. 非自愿上下文切换变多了,说明进程都在被强制调度,也就是都在争抢CPU,说明CPU的确成了瓶颈。

3. 中断次数多了,说明CPU被中断处理程序占用,还需要通过查看/proc/interrupts文件来分析具体的中断类型。

小结

通过sysbench案例,学习了上下文切换问题的分析思路。碰到上下文切换次数过多的问题时,我们可以借助vmstat、pidstat和/proc/interrupts等工具,来辅助排除性能问题的根源

举报

相关推荐

0 条评论