Linux 常见的 CPU 性能问题及解决方案梳理( 三 )

  • 通进程的线程切换,只需要切换线程私有数据、寄存器等不共享数据 。
  • 中断上下文切换中断处理会打断进程的正常调度和执行,转而调用中断处理程序,响应设备事件 。而在打断其他进程时,就需要将进程当前的状态保存下来,这样在中断结束后,进程仍然可以从原来的状态恢复运行 。
    对同一个 CPU 来说,中断处理比进程拥有更高的优先级,所以中断上下文切换并不会与进程上下文切换同时发生 。由于中断会打断正常进程的调度和执行,所以大部分中断处理程序都短小精悍,以便尽可能快的执行结束 。
    查看系统上下文切换vmstat:工具可以查看系统的内存、CPU 上下文切换以及中断次数:
    // 每隔1秒输出$ vmstat 1procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- rbswpdfreebuffcachesisobiboincs us sy id wa st 300 157256 3241604 514444400200 26503 33960 187 75001700 159984 3241708 514445200120 29560 37696 15 10 7500 600 162044 3241816 5144456008120 30683 38861 17 10 7300cs:则为每秒的上下文切换次数 。
    in:则为每秒的中断次数 。
    r:就绪队列长度,正在运行或等待 CPU 的进程 。
    b:不可中断睡眠状态的进程数,例如正在和硬件交互 。
    pidstat:使用pidstat -w选项查看具体进程的上下文切换次数:
    $ pidstat -w -p 3217281 110:19:13UIDPIDcswch/s nvcswch/sCommand10:19:14032172810.0018.00stress10:19:15032172810.0018.00stress10:19:16032172810.0028.71stress其中cswch/s和nvcswch/s表示自愿上下文切换和非自愿上下文切换 。
    自愿上下文切换:是指进程无法获取所需资源,导致的上下文切换 。比如说,I/O、内存等系统资源不足时,就会发生自愿上下文切换 。
    非自愿上下文切换:则是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换 。比如说,大量进程都在争抢 CPU 时,就容易发生非自愿上下文切换
    案例问题排查这里我们使用sysbench工具模拟上下文切换问题 。
    先使用vmstat 1查看当前上下文切换信息:
    $ vmstat 1procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- rbswpdfreebuffcachesisobiboincs us sy id wa st 200 514540 3364828 53233560010160041 9500 100 514316 3364932 53234080080 27900 34809 17 10 7300 100 507036 3365008 53235000080 23750 30058 199 7200然后使用sysbench --threads=64 --max-time=300 threads run模拟 64 个线程执行任务,此时我们再次vmstat 1查看上下文切换信息:
    $ vmstat 1procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- rbswpdfreebuffcachesisobiboincs us sy id wa st 200 318792 3385728 54742720010160041 9500 100 307492 3385756 54743160080 15710 20569 208 7200 100 330032 3385824 547437600816 21573 26844 199 7200 200 321264 3385876 547439600120 21218 26100 207 7300 600 320172 3385932 547444000120 19363 23969 198 73001400 323488 3385980 54748280064788 111647 3745536 24 61 15001400 323576 3386028 54748560080 118383 4317546 25 64 11001600 315560 3386100 547505600816 115253 4553099 22 68900我们可以明显的观察到:
    1. 当前 cs、in 此时剧增 。
    2. sy+us 的 CPU 占用超过 90% 。
    3. r 就绪队列长度达到 16 个超过了 CPU 核心数 8 个 。
    分析 cs 上下文切换问题我们使用pidstat查看当前 CPU 信息和具体的进程上下文切换信息:
    // -w表示查看进程切换信息,-u查看CPU信息,-t查看线程切换信息$ pidstat -w -u -t 110:35:01UIDPID%usr %system%guest%CPUCPUCommand10:35:020338347867.33100.000.00100.001sysbench10:35:01UIDPIDcswch/s nvcswch/sCommand10:45:3903509357-1.000.00kworker/2:210:45:390-35093571.000.00|__kworker/2:210:45:390-350970238478.0045587.00|__sysbench10:45:390-350970339913.0041565.00|__sysbench所以我们可以看到大量的sysbench线程存在很多的上下文切换 。
    分析 in 中断问题我们可以查看系统的watch -d cat /proc/softirqs以及watch -d cat /proc/interrupts来查看系统的软中断和硬中断(内核中断) 。我们这里主要观察/proc/interrupts即可 。
    $ watch -d cat /proc/interruptsRES:900997016912023527904378994902594579899800739897500263895024925895452133Rescheduling interrupts这里明显看出重调度中断(RES)增多,这个中断表示唤醒空闲状态 CPU 来调度新任务执行,
    总结
    1. 自愿上下文切换变多了,说明进程都在等待资源,有可能发生了 I/O 等其他问题 。
    2. 非自愿上下文切换变多了,说明进程都在被强制调度,也就是都在争抢 CPU,说明 CPU 的确成了瓶颈 。
    3. 中断次数变多了,说明 CPU 被中断处理程序占用,还需要通过查看/proc/interrupts文件来分析具体的中断类型 。


      推荐阅读