美文网首页
2020-10-09 CPU上下文分析(四)

2020-10-09 CPU上下文分析(四)

作者: testerPM | 来源:发表于2020-10-10 15:37 被阅读0次

    参考文章:https://www.cnblogs.com/winclpt/articles/10873024.html
    https://blog.51cto.com/12924846/2406421

    CPU上下文切换

    问题1:为什么会出现cpu上下文切换?

    举例子:
    (1) window系统可不可以同时多个人用同一个账号登录?答:不可以
    会把上一个人顶掉。
    (2) linux系统,可不可以同时多个人用同一个账号登录? 答:可以
    因为:Linux是一个多任务操作系统,它支持远大与cpu数量的任务同时运行,这些任务实际上并不是真的在同时运行,而是系统在很短的时间内,将cpu轮流分配给这些任务,从而不可避免的出现cpu资源抢夺,进而导致cpu上下文切换。

    问题2:什么是cpu上下文切换?

    CPU在不同的任务之间切换需要保存任务的运行资源记录,cpu都需要知道任务从哪里加载,又从哪里开始运行,也就是说需要系统事先帮它设置好cpu寄存器和程序计数器。
    cpu寄存器: 是cpu内置的容量小,但速度极快的内存。如指令寄存器(Instruction Register,IR)用来保存当前正在执行的一条指令
    程序计算器:用来指出下一条指令在主存储器中的地址。

    总结:寄存器和程序计算器都是cpu运行任务之前必须依赖的环境,也被叫做cpu上下文。
    什么是cpu上下文切换?答: 先把前一个任务的cpu(也就是cpu寄存器或者程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后跳转到程序计数器所指的新位置,运行新任务。

    cpu上下文切换分类

    根据任务的不同,cpu上下文切换可以分为不同的场景:进程上下文切换,线程上下文切换,中断上下文切换。

    (1)进程上下文切换

    a. 用户态和内核态

    Linux按照特权等级,把进程的运行空间分为内核空间和用户空间。
    内核空间就是%system ,具有最高权限,可以直接访问所有资源。
    用户空间就是%user,只能访问受限资源,不能直接访问内存等硬件设备,比如java程序往内存,磁盘写入,需要通过系统调用才能访问的这些特权资源。
    换言之,进程既可以在用户空间运行,又可以在内核空间中运行(通过系统调用)。进程在用户空间运行时,被称为进程的用户态,而陷入内核空间的时候,被称为进程的内核态。

    b.系统调用
    b.1系统调用过程

    从用户态到内核态的转变,需要通过系统调用来完成。比如,当我们查看文件内容时,就需要多次系统调用来完成:首先调用 open() 打开文件,然后调用 read() 读取文件内容,并调用 write() 将内容写到标准输出,最后再调用 close() 关闭文件。

    b.2系统调用有没有发生cpu上下文切换?

    答案:是肯定的,会发生cpu上下文切换。
    用户态到内核态的转变, CPU 寄存器里需要把原来用户态的指令位置,先保存起来。接着,为了切换到内核态执行内核态代码,CPU 寄存器需要获取内核态指令的新位置。最后才是跳转到内核态运行内核任务(这里实现第一次切换)。 而系统调用结束后,CPU 寄存器需要恢复原来用户保存的状态,然后再切换到用户空间,继续运行进程(这里实现第二次切换)。所以,一次系统调用的过程,其实是发生了两次 CPU 上下文切换。

    c.系统调用和进程上下文切换的区别

    c.1 进程上下文切换,是指从一个进程切换到另一个进程运行。而系统调用的过程中是在同一个进程中运行(所以系统调用的过程被称为特权模式切换,而不是上下文切换,但是实际上,系统调用过程中,cpu上下文切换是不可避免的)。

    c.2进程是由内核来管理和调度的,进程的切换只能发生在内核态。
    所以,进程的上下文不仅包括了虚拟内存、栈、全局变量等用户空间的资源(%user),还包括了内核堆栈、寄存器等内核空间的状态(%system)。

    d .进程上下文切换导致的性能问题

    进程的上下文切换:在保存当前进程的内核状态和 CPU 寄存器之前,需要先把该进程的虚拟内存、栈等保存下来;而加载了下一进程的内核态后,还需要刷新进程的虚拟内存和用户栈。
    而保存上下文和恢复上下文的过程并不是“免费”的,需要内核在 CPU 上运行才能完成。
    在进程上下文切换次数较多的情况下,很容易导致 CPU 将大量时间耗费在寄存器、内核栈以及虚拟内存等资源的保存和恢复上,进而大大缩短了真正运行进程的时间。所以这也是导致平均负载升高的一个重要因素。

    e.%user和%system占用比较高,区别在哪里?

    硬中断,软中断次数比较多,或者磁盘io比较频繁会导致%system(内核态)比较高
    java程序占用cpu比较高,%usr就会比较高。

    (2)线程上下文切换

    线程与进程的最大区别在于: 线程是调度的基本单位,而进程是资源拥有的基本单位。内核中的任务调度,实际上的调度对象是线程。进程只是给线程提供了虚拟内存,全局变量等资源。对于线程和进程,我们可以这么理解:

    1.当进程只有一个线程时,可以认为进程就等于线程。
    2.当进程拥有多个线程时,这些线程会共享相同的虚拟内存和全局变量等资源。这些资源在上下文切换时是不需要修改的。
    3.另外,线程也有自己的私有数据,比如栈和寄存器等,这些在上下文切换时也是需要保存的。
    

    线程的上下文切换其实就可以分为两种情况:

        第一种, 前后两个线程属于不同进程。此时,因为资源不共享,所以切换过程就跟进程上下文切换是一样。
    
        第二种,前后两个线程属于同一个进程。此时,因为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保持不动,只需要切换线程的私有数据、寄存器等不共享的数据。
    

    到这里你应该也发现了,虽然同为上下文切换,但同进程内的线程切换,要比多进程间的切换消耗更少的资源,而这,也正是多线程代替多进程的一个优势。

    (3)中断上下文切换

    为了快速响应硬件的事件,中断处理会打断进程的正常调度和执行,转而调用中断处理程序,响应设备事件。而在打断其他进程时,就需要将进程当前的状态保存下来,这样在中断结束后,进程仍然可以从原来的状态恢复运行。
    举例说明:正在微信视频,突然有电话进来(此时微信视频被中断)此时如果接完电话或者直接挂掉电话,微信视频可继续接通,不会被自动挂断。

    对同一个 CPU 来说,中断处理比进程拥有更高的优先级,所以中断上下文切换并不会与进程上下文切换同时发生。同样道理,由于中断会打断正常进程的调度和执行,所以大部分中断处理程序都短小精悍,以便尽可能快的执行结束。
    另外,跟进程上下文切换一样,中断上下文切换也需要消耗 CPU,切换次数过多也会耗费大量的 CPU,甚至严重降低系统的整体性能。所以,当你发现中断次数过多时,就需要注意去排查它是否会给你的系统带来严重的性能问题。

    总结

    1.cpu上下文切换,是保持Linux系统正常运行的核心功能之一(即是linux系统自带的机制),一般情况不需要我们特别关注。
    2.但是过多的上下文切换,会把cpu时间消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢复上,从而缩短了进程真正运行的时间,导致系统性能下降。

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

    既然过多的上下文切换会把CPU的时间消耗在上下文环境的保存上,并没有充分利用其计算功能。那就需要查看当前系统的上下文切换情况了。

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

    操作分析过程如下:

    1. 打开第一个终端运行sysbench,模拟系统多线程调度的瓶颈

    前提:已安装sysbench,如果没有安装,需要安装才能使用此工具。

    群文件下载安装包:sysbench.tar.gz

    安装步骤:
    1.解压
    2.cd /sysbench
    3./configure
    4.make& make install
    运行10个线程跑5分钟的测试,模拟多线程切换。
    sysbench --threads=10 --time=300 threads run

    image.png

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

    vmstat 3 (每3秒输出一组数据)

    image.png

    参数含义:
    (1) procs

    r(Runing or Runnable):表示正在运行和等待cpu时间片的进程数,这个值如果长期大于系统cpu核数,说明cpu不足,出现了过载

    b(Blocked):表示在等待资源的进程数(即不可中断睡眠状态的进程数),比如正在等待I/O或者内存交换

    (2)memory
    swpd: 表示切换到内存交换区的内存大小(单位KB),也就是虚拟内存的大小。如果swap值不为0或者比较大,只要si,so的值长期为0,这种情况一般属于正常情况。
    free: 表示当前空闲的物理内存(单位:KB)

    buff: 表示bufferscached内存大小,也就是缓冲大小。一般对块设备的读写才需要缓冲。
    cache: 表示 pagecache的内存大小,也就是缓存大小,一般为文件系统进行缓冲,频繁访问的文件都会缓存,如果cache值非常大说明缓存文件比较多,这个时候io中的bi比较小,说明文件系统效率比较好。

    (3)swap
    si: 内存进入到内存交换区的内存大小
    so: 内存交换区进入内存的内存大小
    一般情况下,si,so的值都为0,如果si,so的长期不为0 ,说明系统内存不足,需要增加系统内存。

    io:

    bi: 读磁盘,单位kb/s
    bo:写磁盘。单位kb/s

    (4) system

    in(interrupt): 表示某一时间间隔内的每秒设备中断数(即每秒的中断的次数)
    cs(centext switch):表示每秒产生的上下文切换次数
    这2个值越大,则由内核消耗的cpu就越多

    (5) cpu
    us: 用户态cpu占用的百分比,us值越高,说明用户进程消耗cpu时间越多
    sy: 系统内核进程消耗的cpu时间的百分比

    一般来说us+sy 应该小于80%,如果大于80%,说明cpu处于瓶颈

    id: 表示cpu处于空闲状态的时间百分比

    wa: 等待cpu的时间备份比,wa值越高,说明I/O等待越严重,参考值:不能超过20%
    引起I/O等待的原因可能是磁盘大量随机读写操作造成的

    上面几个参数,需要重点关注的是: r , us , sy ,wa

    参考:https://www.jianshu.com/p/1c80cd47e8cf

    vmstat输出结果解析:

    从上面可以看到明显变化的是cs列,从117一下子升到80多万,同时观察其他几个指标:
    r列: 超过了cpu内核4,也就是我们的cpu的核数,说明有大量的cpu竞争
    us和sy列,这两列的cpu使用率加起来已经上升到85%左右了。sy差不多60多了,说明cpu主要被内核态占用(发生过多的非自愿上下文切换导致sy升高)。
    in列: 中断次数也上升到了2万多
    从上面这几个指标看,系统的就绪队列(r)过长,也就是正在运行和等待cpu的进程数过多导致了大量的上下文切换,而上下文切换又导致了系统cpu占用率(us+sy)升高。

    问题:是哪个进程导致的这些问题呢???----》pidstat来定位

    3.打开第三个终端,运行 pidstat -wu 1

    -w: 输出 进程切换次数
    -u: 输出cpu使用指标
    1: 1秒钟输出一次

    image.png

    从pidstat的输出可以发现,cpu使用率的升高是sysbench导致的,它的cpu使用率已经高达350%左右了。

    上图重点关注2个参数列:
    cswch/s: 每秒自愿上下文切换的次数,是指进程无法获取所需资源,导致的上文切换,如:I/O,内存能资源不足,就会发生自愿的上下文切换。
    nvcwsch/s: 每秒非自愿上下文切换的次数。是指进程由于时间片已到等原因,被系统强制调度,发生的上下切换。如,大量进程都在抢夺cpu时,就会发生非自愿上下文切换。

    从上面的pidstat -wu 1 输出可以看到 上下文切换次数很少,比vmstat看到的80多万明显少了很多,那么这个时候要怎么继续分析呢?-》

    答:pidstat这里主要监控进程,但是Linux调度的基本单位实际上是线程。上图sysbench(是主线程)进程的上下文切换次数看起来不是很多,但是下图它的子线程的上下文切换次数很多。


    image.png

    上次文切换次数主要监控哪些方面:自愿上下文切换次数,非自愿上下文切换次数,中断上下文切换。

    总结

    每秒上下文切换多少次算正常?

    这个数值主要取决于系统CPU的性能,如果上下文切换比较稳定,那在1万以下都算是正常,如果超过1万或者切换次数出现很大的增长,就很可能出现了性能问题。
    
    cswch ,自愿上下文切换的次数增多了,说明系统正在等待资源,有可能发生了I/O等其它问题;
    
    nvcswch ,非自愿上下文切换的次数增多了,说明进程都在强制调度,也就是在争抢CPU,说明CPU过载了即性能出现了瓶颈,此时可能需要增加cpu核数。
    
    in,中断次数增多了,说明CPU被中断,通过分析/proc/interrupt文件来确认中断类型。
    
    

    相关文章

      网友评论

          本文标题:2020-10-09 CPU上下文分析(四)

          本文链接:https://www.haomeiwen.com/subject/umelpktx.html