刚开完会出来,问题少年小明又跑过来找我问问题了,我自然做好准备接受他的挑战啦。
小明:小堂,上次聊起了CPU相关知识,我很感兴趣,能不能再给我说说。比如经常说的CPU上下文切换?
我:行啊,那就继续讲讲CPU上下文切换。
上次聊到Linux是一个多任务操作系统,CPU会运行超过起本身数量的任务。在每个任务运行前,CPU 都需要知道任务从哪里加载、又从哪里开始运行,也就是说,需要系统事先帮它设置好CPU 寄存器和程序计数器(Program Counter,PC)。
它们都是CPU在运行任何任务前,必须的依赖环境,因此也被叫做CPU 上下文。
而CPU 上下文切换,就是先把前一个任务的 CPU 上下文(也就是 CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。
你可以想象CPU是一个忙碌的快递小哥,他需要负责很多个地区派件工作,所以他需要在派件前准备清单和包裹等等东西,这就是称为CPU上下文;而他被派到另外一个区时,就要把未派完的件放回工作站,拿起另一个区的件去派了,则也称为CPU上下文切换。
小明:如果CPU是个人,那肯定难受死了,就算派件不多,但是不停了要换地区工作,这样来来回回跑,也扛不住啊。那什么时候才会上下文切换呢?
我:的确是啊,所以说CPU出现频繁上下文切换,就要注意可能有性能风险了,实际中,根据任务的不同,CPU 的上下文切换就可以分为几个不同的场景,也就是进程上下文切换、线程上下文切换以及中断上下文切换。
进程上下文切换,是指从一个进程切换到另一个进程运行,有一定的性能代价;
如果前后两个线程属于不同进程。此时,因为资源不共享,所以切换过程就跟进程上下文切换是一样。
如果前后两个线程属于同一个进程。此时,因为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保持不动,只需要切换线程的私有数据、寄存器等不共享的数据。
中断处理比进程拥有更高的优先级,会直接打断正常进程运行,如键盘输入,所以大部分中断处理程序都短小精悍,以便尽可能快的执行结束。但切换次数过多也会耗费大量的 CPU,甚至严重降低系统的整体性能。
小明:原来CPU上下文切换也有这么多学问,那我应该怎么定位是不是上下文切换的问题呢?
我:那接下来我就说说怎么查询上下文的情况。
vmstat是一个比较常用的工具
# 每隔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
0 0 0 7005360 91564 818900 0 0 0 0 25 33 0 0 100 0 0
cs(context switch)是每秒上下文切换的次数。
in(interrupt)则是每秒中断的次数。
如果发现上下文切换异常,可以使用pidstat进行跟踪;
# -w参数表示输出进程切换指标,而-u参数则表示输出CPU使用指标
$ pidstat -w -u 1
08:06:33 UID PID %usr %system %guest %wait %CPU CPU Command
08:06:34 0 10488 30.00 100.00 0.00 0.00 100.00 0 sysbench
08:06:34 0 26326 0.00 1.00 0.00 0.00 1.00 0 kworker/u4:2
08:06:33 UID PID cswch/s nvcswch/s Command
08:06:34 0 8 11.00 0.00 rcu_sched
08:06:34 0 16 1.00 0.00 ksoftirqd/1
08:06:34 0 471 1.00 0.00 hv_balloon
08:06:34 0 1230 1.00 0.00 iscsid
08:06:34 0 4089 1.00 0.00 kworker/1:5
08:06:34 0 4333 1.00 0.00 kworker/0:3
08:06:34 0 10499 1.00 224.00 pidstat
08:06:34 0 26326 236.00 0.00 kworker/u4:2
08:06:34 1000 26784 223.00 0.00 sshd
一个是 cswch ,表示每秒自愿上下文切换(voluntary context switches)的次数;
另一个则是 nvcswch ,表示每秒非自愿上下文切换(non voluntary context switches)的次数。
- 所谓自愿上下文切换,是指进程无法获取所需资源,导致的上下文切换。比如说, I/O、内存等系统资源不足时,就会发生自愿上下文切换。
- 而非自愿上下文切换,则是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。比如说,大量进程都在争抢 CPU 时,就容易发生非自愿上下文切换。
小明:那应该怎么判断每秒上下文切换多少次才算正常呢?
我:一般来说,当上下文切换次数超过一万次,或者切换次数出现数量级的增长时,就很可能已经出现了性能问题。
性能评估在实际场景中往往会更为复杂,不是从一两个维度上去看就能解决,后续会把一些经验分享出来给大家。
最新评论