Linux性能分析 – CPU篇

一、性能分析负载均衡的理解

平均负载是指单位时间内,处于可运行状态和不可中断状态的进程数。包括了正在使用 CPU 的进程,还包括等待 CPU 和等待I/O 的进程。

不可中断状态实际上是系统对进程和硬件设备的一种保护机制

平均负载高有可能是 CPU 密集型进程导致的;
平均负载高并不一定代表 CPU 使用率高,还有可能是 I/O 更繁忙了;
大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高;
当发现负载高的时候,你可以使用 mpstat、pidstat 等工具,辅助分析负载的来源

stress 是一个 Linux 系统压力测试工具,这里我们用作异常进程模拟平均负载升高的场景

# -d 参数表示高亮显示变化的区域
$ watch -d uptime

模拟一个 CPU 使用率 100% 的场景
$ stress --cpu 1 --timeout 600

模拟 I/O 压力,即不停地执行 sync
$ stress -i 1 --timeout 600

模拟的是 8 个进程
$ stress -c 8 --timeout 600

sysstat 包含了常用的 Linux 性能工具,用来监控和分析系统的性能。我们的案例会用到这个包的两个命令 mpstat 和 pidstat。
mpstat 是一个常用的多核 CPU 性能分析工具,用来实时查看每个 CPU 的性能指标,以及所有 CPU 的平均指标。
pidstat 是一个常用的进程性能分析工具,用来实时查看进程的 CPU、内存、I/O 以及上下文切换等性能指标。

# -P ALL 表示监控所有 CPU,后面数字 5 表示间隔 5 秒后输出一组数据
$ mpstat -P ALL 5

# 间隔 5 秒后输出一组数据
$ pidstat -u 5 1

# 显示所有 CPU 的指标,并在间隔 5 秒输出一组数据
$ mpstat -P ALL 5 1

二、CPU上下文切换

CPU 寄存器,是 CPU 内置的容量小、但速度极快的内存。而程序计数器,则是用来存储CPU 正在执行的指令位置、或者即将执行的下一条指令位置。它们都是 CPU 在运行任何任务前,必须的依赖环境,因此也被叫做 CPU 上下文。CPU 上下文切换,就是先把前一个任务的 CPU 上下文(也就是 CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。

根据任务的不同,CPU 的上下文切换就可以分为几个不同的场景,也就是进程上下文切换、线程上下文切换以及中断上下文切换

进程上下文切换
Linux 按照特权等级,把进程的运行空间分为内核空间和用户空间,CPU 特权等级的 Ring 0 和 Ring 3。
内核空间(Ring 0)具有最高权限,可以直接访问所有资源;
用户空间(Ring 3)只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统调用陷入到内核中,才能访问这些特权资源。

系统调用过程通常称为特权模式切换,而不是上下文切换。
线程是调度的基本单位,而进程则是资源拥有的基本单位

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

   xwq@xwq:~$ 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 6493448  62204 957172    0    0    78    20 1698  969  4  1 93  2  0
     0  0      0 6492728  62204 957204    0    0     0     0  191  441  0  0 100  0  0
  • cs(context switch)是每秒上下文切换的次数。
  • in(interrupt)则是每秒中断的次数。
  • r(Running or Runnable)是就绪队列的长度,也就是正在运行和等待 CPU 的进程数。
  • b(Blocked)则是处于不可中断睡眠状态的进程数。

pidstat 给它加上 -w 选项可以查看每个进程上下文切换的情况了

xwq@xwq:~$ pidstat -w 5
Linux 4.15.0-30deepin-generic (xwq)     2019年07月30日     _x86_64_    (2 CPU)

17时02分20秒   UID       PID   cswch/s nvcswch/s  Command
17时02分25秒     0         8      9.38      0.00  rcu_sched
17时02分25秒     0        11      0.20      0.00  watchdog/0
17时02分25秒     0        14      0.20      0.00  watchdog/1
17时02分25秒     0       849      2.99      0.20  Xorg

这个结果中有两列内容是我们的重点关注对象。一个是 cswch ,表示每秒自愿上下文切换(voluntary context switches)的次数,另一个则是 nvcswch ,表示每秒非自愿上下文切换(non voluntary context switches)的次数。

所谓自愿上下文切换,是指进程无法获取所需资源,导致的上下文切换。比如说,I/O、内存等系统资源不足时,就会发生自愿上下文切换。
而非自愿上下文切换,则是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。比如说,大量进程都在争抢 CPU 时,就容易发生非自愿上下文切换。

sysbench 是一个多线程的基准测试工具,一般用来评估不同系统参数下的数据库负载情况。

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

# 每隔 1 秒输出 1 组数据(需要 Ctrl+C 才结束)
# -w 参数表示输出进程切换指标,而 -u 参数则表示输出 CPU 使用指标
$ pidstat -w -u 1

# 每隔 1 秒输出一组数据(需要 Ctrl+C 才结束)
# -wt 参数表示输出线程的上下文切换指标
$ pidstat -wt 1

三、cpu达到100%怎么办

/proc/stat提供的就是系统的 CPU 和任务统计信息

# 只保留各个 CPU 的数据
$ cat /proc/stat | grep ^cpu

输出数据解析:

  • user(通常缩写为 us),代表用户态 CPU 时间。注意,它不包括下面的 nice 时间,但包括了 guest 时间。
  • nice(通常缩写为 ni),代表低优先级用户态 CPU 时间,也就是进程的 nice 值被调整为 1-19 之间时的 CPU 时间。这里注意,nice 可取值范围是 -20 到 19,数值越大,优先级反而越低。
  • system(通常缩写为 sys),代表内核态 CPU 时间。
  • idle(通常缩写为 id),代表空闲时间。注意,它不包括等待 I/O 的时间(iowait)。
  • iowait(通常缩写为 wa),代表等待 I/O 的 CPU 时间。
  • irq(通常缩写为 hi),代表处理硬中断的 CPU 时间。
  • softirq(通常缩写为 si),代表处理软中断的 CPU 时间。
  • steal(通常缩写为 st),代表当系统运行在虚拟机中的时候,被其他虚拟机占用的CPU 时间。
  • guest(通常缩写为 guest),代表通过虚拟化运行其他操作系统的时间,也就是运行虚拟机的 CPU 时间。
  • guest_nice(通常缩写为 gnice),代表以低优先级运行虚拟机的时间。

perf工具使用

# 记录性能事件,等待大约 15 秒后按 Ctrl+C 退出
$ perf record -g
# 查看报告
$ perf report

top命令详解:

  • R 是 Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行。
  • D 是 Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断。
  • Z 是 Zombie 的缩写,如果你玩过“植物大战僵尸”这款游戏,应该知道它的意思。它表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID 等)。
  • S 是 Interruptible Sleep 的缩写,也就是可中断状态睡眠,表示进程因为等待某个事件而被系统挂起。当进程等待的事件发生时,它会被唤醒并进入 R 状态。
  • I 是 Idle 的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件交互导致的不可中断进程用 D 表示,但对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况。要注意,D 状态的进程会导致平均负载升高, I 状态的进程却不会。

top ,可以查看进程的状态,这些状态包括运行(R)、空闲(I)、不可中断睡眠(D)、可中断睡眠(S)、僵尸(Z)以及暂停(T)等


top 输出界面的顶端,也显示了系统整体的内存使用情况,这些数据跟 free 类似不再重复解释。我们接着看下面的内容,跟内存相关的几列数据,比如 VIRT、RES、SHR 以及 %MEM 等。

这些数据,包含了进程最重要的几个内存使用情况,挨个来看:

  • VIRT 是进程虚拟内存的大小,只要是进程申请过的内存,即便还没有真正分配物理内存,也会计算在内。
  • RES 是常驻内存的大小,也就是进程实际使用的物理内存大小,但不包括 Swap 和共享内存。
  • SHR 是共享内存的大小,比如与其他进程共同使用的共享内存、加载的动态链接库以及程序的代码段等。
  • %MEM 是进程使用物理内存占系统总内存的百分比。
|| 版权声明
作者:废权
链接:https://blog.yjscloud.com/archives/116
声明:如无特别声明本文即为原创文章仅代表个人观点,版权归《废权的博客》所有,欢迎转载,转载请保留原文链接。
THE END
分享
二维码
Linux性能分析 – CPU篇
一、性能分析负载均衡的理解 平均负载是指单位时间内,处于可运行状态和不可中断状态的进程数。包括了正在使用 CPU 的进程,还包括等待 CPU 和等待I/O 的进程……
<<上一篇
下一篇>>
文章目录
关闭
目 录