linux性能分析(二)——CPU上下文切换分析

目录

一、CPU上下文概念和种类

二、进程上下文切换

三、线程上下文切换

四、中断上下文切换

五、系统中断上下文切换分析工具

六、案例分析

七、切换分析思路总结:


一、CPU上下文概念和种类

        Linux是一个多任务操作系统,可以支持远大于CPU数量的任务,但是任务并非真正的在同时运行,而是CPU快速切换到不同的任务进行执行,造成一种多任务同时执行的错觉。而在CPU切换到其他任务执行之前,为了确保在切换任务之后还能够继续切换回原来的任务继续执行,并且看起来是一种连续的状态,就必须将任务的状态保持起来,以便恢复原始任务时能够继续之前的状态执行。

        那么状态保存的位置位于CPU寄存器和程序计数器(PC寄存器)中。CPU寄存器内存小,但是速度极快,保存程序的堆栈(数据段信息),程序计数器保存程序的下一条指令的位置(代码段信息)。

        因此,CPU上下文就是指CPU寄存器和程序计数器中保存的任务状态信息;CPU上下文切换就是把前一个任务的CPU上下文保存起来,然后加载下一个任务的上下文到这些寄存器和程序计数器,再跳转到程序计数器所指示的位置运行程序。CPU上下文种类切换包括:

  • 进程上下文切换
  • 线程上下文切换
  • 中断上下文切换

二、进程上下文切换

       1、进程上下文切换:

           过程如下:

         进程可运行于用户态和内核态,因此进程上下文保存的信息主要包括:虚拟内存、堆栈、全局变量等用户空间资源,内核堆栈、寄存器等内核空间资源。

        2、这里需要相关的介绍一下系统调用以及跟进程上下文切换的区别。

        前面说到进程可在用户态和内核态运行,用户态和内核态是属于CPU不同的特权等级,内核态拥有最高的特权等级,可以访问任何资源,用户态只能访问有限的资源,那么进程从用户态陷入内核态就是系统调用,比如查看文件的过程:先open打开文件,然后read读取内容,再wirte到终端,最后close关闭文件,这些接口都是属于系统调用。

       系统调用之前,用户态的指令位置需要先在CPU寄存器中保存起来,然后更新为内核态的指令位置,最后才是跳转到内核态运行。系统调用之后,CPU寄存器需要恢复之前保存的用户态,然后再切换到用户控件,因此,系统调用涉及到两次CPU上下文切换。那么系统调用和进程切换的区别是: 

  • 进程切换是在不同的进程间切换,而系统调用是在同一进程内切换,只是在不同的CPU特权等级之间转换。
  • 进程切换比系统调用多了一步,在保存当前进程的内核状态和CPU寄存器之前,进程切换还需要保存虚拟内存和堆栈。

       3、进程切换对系统性能的影响

        每一次进程切换都需要几十纳秒到数微妙的时间,这个时间是比较可观的,如果大量的进程进程切换,回导致大量CPU消耗在寄存器、内核堆栈、虚拟内存的保存和恢复上,进而缩短了进程运行的时间,导致系统负载升高。

        4、进程何时被调度

  • 进程被分配了一定的时间片,当时间片耗尽,CPU切换到其他的进程运行。
  • 进程资源不足,比如内存不足,网络请求结果返回等待、文件读写等待等情况,要等到资源满足时才能继续运行,这时进程会被挂起,CPU切换到其他进程。
  • 进程通过sleep这种方式主动挂起,让CPU重新调度。
  • 优先级更高的进程需要运行,当前进程被挂起。
  • 发生硬件中断时,CPU上的进程也会被挂起,转而执行中断服务程序。

三、线程上下文切换

    对于线程上下文切换的理解主要以下几点:  

  • 进程是系统资源分配的基本单位,线程是系统任务调度的基本单位,因此,所谓的内核任务调度,实际就是对线程的调度。
  • 当进程只有一个线程时,可以认为线程等于进程。
  • 当进程有多个线程时,这些线程会共享虚拟内存和全局变量等资源,这些资源在上下文切换时不需要修改。

    线程上下文切换的情况:

  • 前后两个线程属于不同的进程,这时线程上下文切换等同于进程上下文切换。
  • 前后两个线程属于同一个进程,这时线程上下文切换不需要改变虚拟内存,只切换线程的私有数据(局部变量)、寄存器等不共享的数据。

    同一进程内的线程切换,比多进程之间的线程切换消耗更多的资源(需要改变虚拟内存、全局变量),因此这也是用多线程替代多进程的原因。

四、中断上下文切换

  • 中断上下文切换是为了快速响应硬件事件,通过中断处理打断进程的正常调度并执行中断服务程序。
  • 中断上下文切换可以打断用户态的进程,但是不需要保存用户态资源(虚拟内存、全局变量),只需要保存内核态资源(CPU寄存器、内核堆栈、硬件中断参数)。
  • 中断上下切换比进程上下文切换具有更高的优先级。由于中断处理会打断正常的进程调度,因此中断服务处理程序都应该短小精悍。

五、系统中断上下文切换分析工具

 1、vmstat是一个系统性能分析工具,常用来分析CPU上下文切换次数和中断的次数。

      常用用法:vmstat 2   #每隔2秒打印一次系统性能中指标。

root@ubuntu:~# vmstat 2
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  10692 627092 306340 1478872    0    0     0     1    1    3  3  2 94  0  0

      主要关注指标:

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

  2、pidstat是一个查看进程性能的分析工具。

       常用用法:pidstat -wt -u 1  #w输出进程切换指标,t输出线程切换指标,u输出CPU使用指标。

root@ubuntu:~# pidstat -wt -u 1
Linux 4.4.0-31-generic (ubuntu)         01/06/2019      _x86_64_        (4 CPU)

11:10:01 PM   UID      TGID       TID    %usr %system  %guest    %CPU   CPU  Command
11:10:02 PM     0         7         -    0.00    1.52    0.00    1.52     0  rcu_sched
11:10:02 PM     0         -         7    0.00    1.52    0.00    1.52     0  |__rcu_sched

11:10:01 PM   UID      TGID       TID   cswch/s nvcswch/s  Command
11:10:02 PM     0         7         -     50.76      0.00  rcu_sched
11:10:02 PM     0         -         7     50.76      0.00  |__rcu_sched

       其中有两列需要重点关注:

  • cswch(voluntary context switches):自愿上下文切换,是指主动式的导致切换,比如IO操作引起的资源等待。
  • nswch(none voluntary context switches):非自愿上下文切换,是指被动式的导致切换,比如时间片到,被系统强制调度,一般大量进程竞争CPU时会导致nswch。

六、案例分析

       1、第一个终端通过sysbench工具模拟多线程切换。

            第一个终端输入:sysbench --num-threads=10 --max-time=3000 --test=threads run

            参数说明:

             --num-threads:启动线程数

             --max-time:运行时间(秒)

             --test:测试集,选择threads,测试线程

     2、第二个终端通过vmstat查看系统性能

lsm@ubuntu:~$ 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
 0  0  10692 608844 306480 1483768    0    0     0     0  200  279  1  1 98  0  0
 7  0  10692 608624 306480 1483768    0    0     0     0 1895 288375  5 35 60  0  0
10  0  10692 608268 306480 1483768    0    0     0     0 7428 1638533  9 76 14  0  0

       观察发现:

  • cs从279飙升到1638533。
  • r队列:升到10,远超过CPU个数4(grep 'model name' /proc/cpuinfo | wc -l查看),已经开始出现CPU竞争。
  • us和sy:升到%85,其中内核CPU高达%76,说明CPU主要被内核占用。
  • in上升到7428,说明中断处理也是问题。

      可见,正是r队列过长,导致大量CPU竞争,引起大量线程上下文切换,而线程上下文切换主要消耗内核态资源,因此导致致内核CPU使用率过高。

      3、第三个终端通过pidstat查看具体进程

lsm@ubuntu:~$ pidstat -wtu 1
Linux 4.4.0-31-generic (ubuntu)         01/07/2019      _x86_64_        (4 CPU)

12:40:05 AM   UID      TGID       TID    %usr %system  %guest    %CPU   CPU  Command
12:40:06 AM     0     53793         -   29.00  303.00    0.00  332.00     2  sysbench
12:40:06 AM     0         -     53794    3.00   30.00    0.00   33.00     0  |__sysbench
12:40:06 AM     0         -     53795    5.00   29.00    0.00   34.00     0  |__sysbench
12:40:06 AM     0         -     53796    3.00   31.00    0.00   34.00     3  |__sysbench
12:40:06 AM     0         -     53797    2.00   30.00    0.00   32.00     3  |__sysbench
12:40:06 AM     0         -     53798    1.00   33.00    0.00   34.00     0  |__sysbench
12:40:06 AM     0         -     53799    2.00   28.00    0.00   30.00     2  |__sysbench
12:40:06 AM     0         -     53800    3.00   30.00    0.00   33.00     3  |__sysbench

12:40:05 AM   UID      TGID       TID   cswch/s nvcswch/s  Command
12:40:06 AM  1000         -     53790      1.00      6.00  |__pidstat
12:40:06 AM     0         -     53794  33029.00 119302.00  |__sysbench
12:40:06 AM     0         -     53795  29024.00 144719.00  |__sysbench
12:40:06 AM     0         -     53796  22800.00 109972.00  |__sysbench
12:40:06 AM     0         -     53797  25421.00 123484.00  |__sysbench
12:40:06 AM     0         -     53798  34135.00 139033.00  |__sysbench
12:40:06 AM     0         -     53799  31236.00 125567.00  |__sysbench
12:40:06 AM     0         -     53800  36826.00 115408.00  |__sysbench

        可见,CPU主要是被sysbench占用,各个子线程加起来达到%332,而nvcswch远大于cswch,是因为所创建的大量线程主要是CPU密集型任务,基于时间片原理而产生调度,属于主动切换,并非IO问题的被动切换。

       4、查看中断发生类型

       通过查看/proc/interrupts这个文件内容,proc是虚拟文件系统,保存了很多内核信息,其中interrupts提供了中断使用情况。

root@ubuntu:~# watch -d cat /proc/interrupts
           CPU0       CPU1       CPU2       CPU3
...
RES:  108297505  105334518  107312897  104255732   Rescheduling interrupts
...

        观察一段时间,发现变化最快的是重调度中断(RES),这个中断表示,唤醒空闲的CPU来调度新的任务执行。所以这种中断数量升高也是因为任务过多。

七、切换分析思路总结:

        1、发现是否出现过多切换问题:如果切换次数比较稳定,那么在数百到一万以内一般都是正常;如果上下文切换超过了一万,或者呈现爆发式增长,就意味着可能出现性能问题。

        2、存在切换过多问题时具体分析属于哪一种情况:

  • cswch变多,说明任务都在等待资源,一般是IO问题。
  • ncswch变多,说明任务由于时间片到了而在被强制调度,一方面说明任务过多,也说明CPU性能有瓶颈。
  • 中断次数变多,说明系统被中断处理程序占用,需要查看/proc/interrupts文件中的变化来具体分析是哪一种中断增多。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值