Linux Preformance Analyze CPU(二) - Linux性能分析之CPU

AI 摘要: 本文介绍了平均负载的概念和CPU负载高的可能原因,以及系统负载分析相关的工具和指标。同时还介绍了使用stress工具进行压力模拟的方法。

1. 平均负载概念

  • 平均负载:单位时间内,可运行状态+不可中断状态=活跃进程数,和CPU使用率不是一个概念(可能负载很高,但CPU使用率很低,比如IO密集型);
    • CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者是一致的;
    • I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;
    • 大量等待CPU的进程调度(上下文切换很频繁的)也会导致平均负载升高,此时的 CPU 使用率也会比较高。
  • R:运行/可运行、D:不可中断(OS的保护进程,属于保护机制)
  • CPU负载高,可能由于用户态、内核态、IO中断、软中断等等导致,并不是一定CPU使用率很高

2. 系统负载分析相关记录

  • uptime/top
  • /proc/cpuinfo
  • 0.7比率
  • stree:压力测试工具
  • systat:性能工具,包含mpstatpidstat
    • mpstat:每个cpu性能情况
    • pidstat:进程性能分析工具

2.1. stress压力模拟

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// IO密集型,执行write()/unlink(),iowait模拟,导致%iowait很高
stress -d 2 --timeout 600 -v

// CPU密集型, 执行sqrt(),导致%usr很高
stress -c 2 --timeout 600 -v

// IO密集型,执行sync(),模拟执行磁盘IO刷新,导致%sys系统调用很高
stress -i 2 --timeout 600 -v

// 执行malloc()/free(),模拟内存申请释放,导致%sys系统调用很高
stress -m 2 --timeout 600 -v

2.2. mpstat和pidstat分析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 系统负载
 # watch -d uptime
...,  load average: 1.00, 0.75, 0.39

// cpu状态
 # mpstat 2
12:29:02 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
12:29:04 AM  all    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
12:29:06 AM  all    0.00    0.00    0.50    0.00    0.00    0.00    0.00    0.00    0.00   99.50
12:29:08 AM  all    0.50    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   99.50

// 进程状态
 # pidstat
12:30:12 AM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
12:30:14 AM     0     13727    0.00    0.50    0.00    0.50     0  pidstat

3. 上下文切换的概念

  • 用户态(ring3)、内核态(ring0)
  • 进程是由OS内存来管理和调度,进程的切换只能发生在内核态;进程的上下文不仅包含虚拟内存、栈、全局变量等用户空间的资源,还包括内核堆栈、寄存器等内核空间的状态
  • 一次系统调用,实际发生了两次CPU上下文切换(一次切换保存、一次恢复执行);系统调用属于同进程内的CPU上下文切换,软中断
  • 线程和进程关系:进程做资源申请和管理的单位,线程作为系统调度和执行的单位
  • 进程或线程在执行过程中,由于系统调用或函数调用亦或是异常或中断都会引发进程或线程的切换
  • 进程调度会引发进程的上下文切换,从而需要保存进程的相关虚拟内存、栈等信息以及相关内核态下的通用寄存器、指令寄存器、程序计数器等资源信息,等下次执行时候再恢复这些信息
    • 时间片用完
    • 高优先级进程抢占
    • 等待IO资源,系统调度其进入到挂起状态
    • 自动挂起(sleep),主动进入到挂起
    • 硬件中断(键盘输入),执行中断服务例程
  • 线程调度:
    • 不同进程的线程调度,同进程上下文切换一致
    • 相同进程的线程调度,仅需要切换线程的私有数据、寄存器信息(开销小于进程切换)
  • 过多的CPU上下文切换,会把CPU的时间消耗在寄存器、内核栈,以及虚拟内存、程序堆栈等数据的保存和恢复上,导致系统整体性能大幅降低
  • 进程自愿和非自愿切换
    • 自愿切换:等待IO等必须要等的资源,主动放弃CPU资源
    • 非自愿切换:时间片用完、别其他进程抢占等,表示CPU资源紧俏,需要考虑是否CPU成为了瓶颈

3.1. 分析

  • vmstat
  • pidstat
  • /proc/meminfo
  • /proc/stat
  • /proc/interrupts

3.2. sysbench模拟系统多线程调度

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

3.3. vmstat分析上下文切换和系统中断

1
2
3
4
5
6
7
// 关注system的in(中断)和cs(系统上下文切换),cpu的us(用户态)和sy(内核态),更多含义man vmstat
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
 1  0      0 737980   7664 157964    0    0     0     0   31   31  0  1 99  0  0
 
// cat /proc/interrupts

3.4. pidstat -w分析上下文切换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// cswch/s : voluntary context switches(自愿切换,IO阻塞资源等待,进程自动放弃CPU资源)
     Total number of voluntary context switches the task made per  sec‐
     ond.  A voluntary context switch occurs when a task blocks because
     it requires a resource that is unavailable.

// nvcswch/s : non voluntary context switches(非自愿切换,时间片用完被OS调度走)
     Total number of non voluntary context switches the task  made  per
     second.  A involuntary context switch takes place when a task exe‐
     cutes for the duration of its time slice and  then  is  forced  to
     relinquish the processor.

// -w表示查看上下文切换,-t表示任务关联的线程
pidstat -wt 1
Average:      UID      TGID       TID   cswch/s nvcswch/s  Command
Average:        0         1         -      0.50      0.00  systemd
Average:        0         -         1      0.50      0.00  |__systemd
Average:        0         3         -      1.99      0.00  ksoftirqd/0
Average:        0         -         3      1.99      0.00  |__ksoftirqd/0