Linux性能优化实战(一)

CPU性能篇


第一篇 如何理解平均负载

系统变慢首先想到的两个命令top和uptime

uptime
02:34:03 up 2 days, 20:14,  1 user,  load average: 0.63, 0.83, 0.88
//当前时间、系统运行时间、当前系统登录用户数、过去1分钟、5分钟、15分钟平均负载

平均负载:简单来说就是单位时间内系统处于可运行状态不可中断状态的平均进程数,也就是平均活跃进程数

可运行状态 处于Runable状态的进程,进程状态标志为R

不可中断状态 一般是等待I/O的进程,进程状态标志位D

  • 如果平均负载为2意味着什么呢?
  • 在一个2核cpu上意味着所有cpu刚好都被占用
  • 在一个4核cpu上意味着cpu有50%的空闲
  • 在一个1核cpu上意味着有一半进程竞争不到cpu
  • 平均负载多少为合理?

平均负载理想的情况为cpu的核数,查询cpu核数通过top命令或者从/proc/cpuinfo中读取。

[root@fengniaoweb proc]# grep 'model name' /proc/cpuinfo | wc -l
4
  • 如果1、5、15分钟都表现很平稳说明系统很平稳不存在过载
  • 如果1、5、15分钟负载是逐渐升高的就要引起注意了,尤其是超过70%的时候

平均负载与CPU使用率

CPU使用率是指单位时间内CPU繁忙情况的统计,而平均负载还包含了不可中断的进程(实际并未使用CPU)

  • CPU密集型进程,平均负载一般与CPU使用率一致
  • I/O密集型进程,平均负载升高CPU使用率不一定会升高
  • 大量等待调度的进程也会让平均负载和CPU使用率一起升高

工具篇

stress是一个linux系统压力测试工具,可以用来模拟系统负载升高的场景

apt install stress  #安装

sysstat包含了linux常用的性能监控分析工具

  • mpstat是一个常用的多核cpu性能分析工具,用来实时查看cpu的性能,以及所有cpu的平均指标
  • pidstat是一个常用的进程性能分析工具,用来实时查看系统的CPU、内存、I/O以及上下文切换等多个指标

第二篇 CPU的上下文切换

背景

Linux是个多任务操作系统,在执行远大于CPU核数的任务时,任务并不是同时进行的,而是操作系统根据调度算法将CPU轮流分配给多个任务执行。

由此任务从哪里开始加载,又从哪里开始执行?

这就需要引入CPU 寄存器和程序计数器(Program Counter,PC)

CPU寄存器:CUP内容量小速度极快的内存

程序计数器:用于存储正在执行的指令位置或者即将执行的下一条指令位置

CPU寄存器和程序计数器是CPU运行任何任务前必须依赖的环境因此也叫CPU上下文

919-1.png

理解CUP上下文切换

先把前一个任务的CPU上下文(也就是CPU寄存器和程序计数器)保存起来,然后加载新任务的上下文并跳转到新任务程序计数器所指位置开始执行新任务的过程。

Linux权限等级

  • 内核空间(Ring0)

​ 拥有最高的权限等级,可以访问系统内所有资源

  • 用户空间(Ring3)

​ 只能访问受限资源,不能直接访问硬件设备,需要通过系统调用才能间访问特权设备

919-2.png

用户态与内核态

进程既可能在用户空间运行,此时称作用户态,又可能在在内核空间运行此时称作内核态,进程一旦发生系统调用就需要从用户态切换到内核态,调用完成后又要从内核态切换回用户态。所以一次系统调用会至少发生两次CPU上下文切换

系统调用发生的上下文切换实际上还是在同一个进程内,所以不会涉及到虚拟内存等进程资源的切换,因此也叫特权模式切换注意与进程上下文切换区分

CPU上下文切换类型

  • 进程的上下文切换

    919-3.png

  • ​ 虚拟内存、栈、全局变量等用户态空间资源切换

  • ​ 内核堆栈、寄存器等内核态空间资源切换

  • 线程的上下文切换

  • 同一个进程内的线程切换,不需要切换虚拟内存、全局变量等共享资源

  • 跨进程的线程切换,等同于进程切换

  • 线程私有的栈和寄存器数据也在切换时也需要考虑保存

  • 中断的上下文切换

  • 中断不涉及到用户态,因此中断的上下文切换只包含CPU寄存器、内核堆栈、中断参数等
    什么时候发生切换?

  • CPU的执行周期以时间片为单位,执行完成后如果还有其他任务等待执行,则自动让出时间片由操作系统从任务队列中选择最靠前的任务执行

  • 进程在等待系统资源(如内存、IO等)时,任务被挂起,操作系统调度其他任务执行

  • 进程调用系统休眠函数比如sleep时,任务被挂起,操作系统调度其他任务执行

  • 有更高优先级任务到来,为保证高优先级任务先执行,当前任务也会被挂起

  • 发生硬件中断时,任务被挂起,转而执行内核中的中断服务程序

怎么查看CPU上下文切换?

VMSTAT是一款常用的系统性能分析工具,主要用来分析系统的内存使用情况、也常用来分析CPU上下文切换和中断的次数。下面为使用示例:

# 每隔 5 秒输出 1 组数据
$ 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 7005360  91564 818900    0    0     0     0   25   33  0  0 100  0  0

重点关注以下4列

cs(context switch)是每秒上下文切换的次数。

in(interrupt)则是每秒中断的次数。

r(Running or Runnable)是就绪队列的长度,也就是正在运行和等待CPU的进程数。

b(Blocked)则是处于不可中断睡眠状态的进程数。

VMSTAT只能给出系统总体的上下文切换情况,想要查看每个进程的详细切换情况,就要使用pidstat命令了,加上-w选项。

# 每隔 5 秒输出 1 组数据
$ pidstat -w 5
Linux 4.15.0 (ubuntu)  09/23/18  _x86_64_  (2 CPU)

08:18:26      UID       PID   cswch/s nvcswch/s  Command
08:18:31        0         1      0.20      0.00  systemd
08:18:31        0         8      5.40      0.00  rcu_sched
...

cswch ,表示每秒自愿上下文切换(voluntary context switches)的次数

nvcswch ,表示每秒非自愿上下文切换(non voluntary context switches)的次数

自愿上下文切换指进程无法获取到资源导致的切换,如等待IO、内存等系统资源时

非自愿上下文切换指大量进程争抢CPU时,由于时间片已到等原因,被迫发生的切换

pidstat使用举例

# 每隔 1 秒输出 1 组数据(需要 Ctrl+C 才结束)
# -w 参数表示输出进程切换指标,而 -u 参数则表示输出 CPU 使用指标
$ pidstat -w -u 1
08:06:33      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
08:06:34        0     10488   30.00  100.00    0.00    0.00  100.00     0  sysbench
08:06:34        0     26326    0.00    1.00    0.00    0.00    1.00     0  kworker/u4:2

08:06:33      UID       PID   cswch/s nvcswch/s  Command
08:06:34        0         8     11.00      0.00  rcu_sched
08:06:34        0        16      1.00      0.00  ksoftirqd/1
08:06:34        0       471      1.00      0.00  hv_balloon
08:06:34        0      1230      1.00      0.00  iscsid
08:06:34        0      4089      1.00      0.00  kworker/1:5
08:06:34        0      4333      1.00      0.00  kworker/0:3
08:06:34        0     10499      1.00    224.00  pidstat
08:06:34        0     26326    236.00      0.00  kworker/u4:2
08:06:34     1000     26784    223.00      0.00  sshd
# 每隔 1 秒输出一组数据(需要 Ctrl+C 才结束)
# -wt 参数表示输出线程的上下文切换指标
$ pidstat -wt 1
08:14:05      UID      TGID       TID   cswch/s nvcswch/s  Command
...
08:14:05        0     10551         -      6.00      0.00  sysbench
08:14:05        0         -     10551      6.00      0.00  |__sysbench
08:14:05        0         -     10552  18911.00 103740.00  |__sysbench
08:14:05        0         -     10553  18915.00 100955.00  |__sysbench
08:14:05        0         -     10554  18827.00 103954.00  |__sysbench
...

如何查看中断次数?

因为中断发生在内核态,所以不能通过pidstat查看,需要从/proc/interrupts 这个只读文件中读取。/proc 实际上是 Linux 的一个虚拟文件系统,用于内核空间与用户空间之间的通信。/proc/interrupts就是这种通信机制的一部分,提供了一个只读的中断使用情况。

# -d 参数表示高亮显示变化的区域
$ watch -d cat /proc/interrupts
           CPU0       CPU1
...
RES:    2450431    5279697   Rescheduling interrupts
...
  • 重调度中断(RES)唤醒空闲状态的CPU来调度新的任务运行
    如何通过切换次数发现问题?
  • 自愿上下文切换变多,说明都在等待资源,有可能发生了IO等其他问题
  • 非自愿上下文切换变多,说明都在争抢CPU资源,CPU成为了瓶颈
  • 中断次数变多了,说明CPU都被中断处理程序占用,需要根据中断类型具体分析原因

此为个人笔记,不涉及其他,仅做参考

你可能感兴趣的:(Linux性能优化实战(一))