Linux 常见性能指标 -- CPU

本系列记录操作系统常见性能指标,写这个主要是记录也是回顾,笔记很长,拆分了几个部分,本篇记录CPU 的性能指标

CPU是计算机中最常见的概念,但是如何衡量CPU是否存在性能瓶颈,需要看哪些指标,可能多少都能说出来,CPU负载高、CPU使用率高、CPU缓存命中率低等等。具体怎样算高,哪些因素影响,如何排查呢?这里简单记录一下一些概念,希望帮助理解。

一、CPU负载

平均负载

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

  

平均负载 = (正在运行的进程数 + 等待运行的进程数) / CPU内核数

1)可运行状态的进程

是指正在使用 CPU 或者正在等待 CPU 的进程

ps 命令看到的,处于 R 状态(Running 或 Runnable)的进程

2)不可中断状态的进程

正处于内核态关键流程中的进程,并且这些流程是不可打断的

ps 命令中看到的 D 状态(Uninterruptible Sleep,也称为 Disk Sleep)的进程

3)top 中看到的负载均衡

top 看到的load average: 0.02, 0.10, 0.05 分别是表示1分钟,5分钟,15分钟的平均负载

如果一个单核CPU平均负载为1,则表示该CPU正在运行一个进程60秒,或者多个进程正在分时运行,使得CPU使用率保持在100%。

但是对于多核CPU,平均负载超过1就表示在满负荷运行了。

看看下文理解平均负载

Understanding Linux CPU Load - when should you be worried? | Scout APM Blog

平均负载高场景

CPU 密集型进程,使用大量 CPU 会导致平均负载升高;

I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;

大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。

分析步骤

分析思路

  1. 平均负载高有可能是 CPU 密集型进程导致的;
  2. 平均负载高并不一定代表 CPU 使用率高,还有可能是 I/O 更繁忙了;
  3. 当发现负载高的时候,你可以使用 mpstat、pidstat 等工具,辅助分析负载的来源

分析步骤

  1. top 命令查看平均负载是否有异常,看看平均负载是否在减小(1分钟 5分钟 15分钟)
  2. pidstat 5 5可以直观看到进程的用户态和系统态CPU使用情况
  3. mpstat 5 5查看是否是IO等待或者中断导致的负载高

注意:

sysstat 11.5.5 以上版本才有%wait字段

sysstat 软件包含了mpstat/iostat/pidstat等软件,而且会通过记录系统的CPU性能数据

默认在/var/log/sa 目录下,可以通过sar -f sa文件查看记录的数据


二、上下文切换

上下文:CPU的任何任务的执行,必须依赖CPU寄存器(CPU 内置的容量小、但速度极快的内存)以及程序计数器(用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置)

上下文切换类型

上下文切换有三类,进程、线程的上下文切换,以及中断上下文切换

1)进程上下文切换

进程从用户态进入内核态时,需要系统调用来完成

系统调用的CPU上下文切换过程(不切换进程):

  1. CPU 寄存器里原来用户态的指令位置,需要先保存起来
  2. 接着,为了执行内核态代码,CPU 寄存器需要更新为内核态指令的新位置
  3. 最后才是跳转到内核态运行内核任务
  4. 系统调用结束后,CPU 寄存器需要恢复原来保存的用户态,再切换到用户空间,继续运行进程

进程上下文切换描述:

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

常见进程切换场景:

  • CPU时间片用完,进程挂起,切换等待CPU的进程
  • 进程在系统资源不足时,等待资源满足后才运行,进程挂起,系统调度其他进程
  • 进程通过sleep函数自主挂起,系统重新调度进程
  • 有优先级更高的进程需要运行时,当前进程挂起,运行高优先级进程
  • 发生硬件中断时,CPU上进程挂起,转而执行内核中的中断服务程序

简单来说就是用完了CPU时间片,或者被抢占了的时候会进程上下文切换

2)线程上下文切换

常见线程上下文切换场景:

  • 前后两个线程属于不同进程,资源不共享,此时与进程上下文切换一样
  • 前后两个线程属于相同进程,虚拟内存和全局变量是共享的,所以只需要切换线程私有的数据、寄存器等不共享的数据

3)中断上下文切换

产生原因

为了快速响应硬件的事件,中断处理会打断进程的正常调度和执行,转而调用中断处理程序,响应设备事件

消耗资源
  • 由于中断上下文不涉及进程的用户态,所以中断过程打断了用户态的进程,也不需要保存和恢复这个进程的虚拟内存、全局变量等用户态资源
  • 中断上下文,其实只包括内核态中断服务程序执行所必需的状态,包括 CPU 寄存器、内核堆栈、硬件中断参数等
中断记录

/proc/interrupts 这个只读文件中读取中断使用情况

中断处理两个阶段
  1. 上半部直接处理硬件请求,也就是我们常说的硬中断,特点是快速执行;
  2. 而下半部则是由内核触发,也就是我们常说的软中断,特点是延迟执行。

例如:

网卡接收到数据包后,通过硬件中断的方式,通知内核有新的数据到了,内核调用中断处理程序响应;

上半部就是将网卡数据读入内存,更新寄存器状态,再发送软中断信号,通知下半部处理;

下半部收到软中断信号唤醒后,从内存中找到网络数据,根据网络协议栈,对数据进行逐层解析处理,直到发送给应用。

上下文切换分析方法

分析思路

  • 自愿上下文切换变多了,说明进程都在等待资源,有可能发生了 I/O 等其他问题
  • 非自愿上下文切换变多了,说明进程都在被强制调度,也就是都在争抢 CPU,说明 CPU 的确成了瓶颈
  • 中断次数变多了,CPU 被中断处理程序占用,需要查看 /proc/interrupts 文件来分析具体的中断类型

分析步骤

pidstat -w 查看系统的上下文切换情况,依据切换类型分析大致原因

cswch(voluntary context switches)自愿上下文切换:

描述:指进程无法获取所需资源,导致的上下文切换

场景:I/O、内存等系统资源不足时,就会发生自愿上下文切换

nvcswch(non voluntary context switches)非自愿上下文切换:

描述:进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换

场景:大量进程都在争抢 CPU 时,就容易发生非自愿上下文切换

注意:pidstat 默认显示进程的指标数据,加上 -t 参数后,才会输出线程的指标


三、CPU使用率

单位时间内 CPU 繁忙情况的统计,跟平均负载并不一定完全对应

我们有时候能在 top 命令的结果里面能看到超过100%的情况,这是因为这个进程占用了多个CPU

top 通过读取 /proc/stat 文件计算CPU利用率,/proc/stat  文件包含各种系统统计信息,包括 CPU 利用率数据。

常用分析思路

mpstat 5 5
  1. 用户 CPU 和 Nice CPU 高,说明用户态进程占用了较多的 CPU,所以应该着重排查进程的性能问题
  2. 系统 CPU 高,说明内核态占用了较多的 CPU,所以应该着重排查内核线程或者系统调用的性能问题
  3. I/O 等待 CPU 高,说明等待 I/O 的时间比较长,所以应该着重排查系统存储 I/O 问题
  4. 软中断和硬中断高,说明软中断或硬中断的处理程序占用较多的 CPU,着重排查内核中的中断服务程序
  5. 碰到常规问题无法解释的 CPU 使用率情况时,首先要想到有可能是短时应用导致的问题
    1. 应用里直接调用了其他二进制程序,这些程序通常运行时间比较短,通过 top 等工具也不容易发现
    2. 应用本身在不停地崩溃重启,而启动过程的资源初始化,很可能会占用相当多的 CPU

常用分析软件

top

默认使用 3 秒时间间隔 \ 默认显示所有CPU的使用率平均值 \ 按1切换到每个CPU的使用率

状态
  • R 是 Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行
  • D 是 Disk Sleep 的缩写,也就是不可中断状态睡眠,一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断
  • Z 是 Zombie 的缩写,进程实际上已经结束了,但父进程还没有回收它的资源(比如进程的描述符、PID 等)
  • S 是 Interruptible Sleep 的缩写,也就是可中断状态睡眠,表示进程因为等待某个事件而被系统挂起。当进程等待的事件发生时,它会被唤醒并进入 R 状态
  • I 是 Idle 的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。
    • 对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况
    • D 状态的进程会导致平均负载升高, I 状态的进程却不会
  • T 或者 t,也就是 Stopped 或 Traced 的缩写,表示进程处于暂停或者跟踪状态
  • X 是 Dead 的缩写,表示进程已经消亡,所以你不会在 top 或者 ps 命令中看到它
处理
  1. 正常情况下,不可中断状态在很短时间内就会结束,如果长时间的不可中断进程出现,考虑IO或硬件问题
  2. 僵尸进程是父进程未正常回收子进程资源,导致的,如果大量且长时间存在,需要及时处理
    1. 查看子进程结束的处理是否正确,比如有没有调用 wait() 或 waitpid(),抑或是,有没有注册 SIGCHLD 信号的处理函数
    2. pstree -aps 僵尸进程pid 找到父进程
      1. a Show command line arguments.
      2. p Show PIDs.
      3. s Show parent processes of the specified process.

僵尸进程持续的时间都比较短,在父进程回收它的资源后就会消亡,或者在父进程退出后,由 init 进程回收后也会消亡;

crond 的定时任务在执行时会大量标准输出时,可能会引起sendmail 的僵尸进程,不会释放,需要重定向标准输出;

ps

使用的是进程的整个生命周期(/proc/stat) 

ps -ef    standard syntax    优点看到父进程
ps aux    BSD syntax         优点看状态和使用情况

perf

perf 是Linux 性能分析工具,可以查看实时的性能数据以及导出和导入性能数据,目前不太熟悉

实例
perf top

实时显示占用 CPU 时钟最多的函数或者指令,因此可以用来查找热点函数(需要累积一定量的事件)

  • Overhead ,是该符号的性能事件在所有采样中的比例,用百分比来表示
  • Shared ,是该函数或指令所在的动态共享对象(Dynamic Shared Object)
  • Object ,是动态共享对象的类型
    • [.] 表示用户空间的可执行程序、或者动态链接库
    • [k] 则表示内核空间
  • Symbol 是符号名,也就是函数名,函数名未知时,用十六进制的地址来表示
perf top -e cycles:k            # 查看内核空间CPU消耗最多的函数
perf top -e cycles:u            # 查看用户空间CPU消耗最多的函数
perf top -g -p pid 

-g开启调用关系分析,-p指定进程号

perf record -g -p  

记录相关信息到perf.data

perf report perf.data

加载文件记录的信息,通常用于解决容器内与宿主机依赖不一致的情况、

dstat

dstat 它吸收了 vmstat、iostat、ifstat 等几种工具的优点,可以同时观察系统的 CPU、磁盘 I/O、网络以及内存使用情况,这个软件来自 pcp-system-tools工具包

dstat --list     # 查看所有可用的插件
dstat            # 默认 -cdngy 参数,可以查看cpu 磁盘IO 网络IO 上下文切换
dstat -at        # 在默认基础上加时间打印

mpstat

mpstat 5 5

压测软件

ab 

Apache HTTP服务器基准测试工具,用来测试网站性能,如下是一次请求10个,共计100个请求

ab -c 10 -n 100 http://localhost:8080/

注意这个得带上末尾的路径,光写端口不行,不要用来测试正常运行的网站!!!

四、CPU缓存命中率

CPU缓存命中率是指CPU在执行操作时,所需数据已经在缓存中的比例。缓存命中率的高低直接影响到CPU的性能表现。

这节内容来自AI生成

理解缓存命中率

  • 缓存命中:当CPU需要读取或写入数据时,如果这些数据已经存储在CPU缓存中,则称为缓存命中,此时CPU可以直接从缓存中快速读取或写入数据。
  • 缓存不命中:如果CPU需要的数据不在缓存中,则需要从主内存(RAM)中读取,这个过程比从缓存中读取要慢得多,这种情况称为缓存不命中。

缓存命中率的影响

  • 性能提升:缓存命中可以显著减少CPU访问主内存的次数,从而提高数据访问速度,提升系统性能。
  • 性能下降:缓存不命中会导致CPU等待从主内存读取数据,增加访问延迟,降低系统性能。

分析和排查方法

1)使用Perf工具:可以使用Perf工具来监测CPU缓存的命中率

  • 这将显示LLC(最后一级缓存)的读取、不命中、写入和写入不命中的统计信息。
perf stat -e LLC-loads,LLC-load-misses,LLC-stores,LLC-store-misses

实测:虚拟机会返回不支持,物理机才有效;按Ctrl+c 停止采集;

2)优化代码和数据结构

  • 紧凑化数据结构:减少数据结构的内存占用,以便更多的数据可以被缓存。
  • 软件预取数据:提前将可能需要的数据加载到缓存中,以增加缓存命中率。
  • 去除伪共享缓存:避免不同线程或进程的数据块共享缓存行,减少缓存不命中。

3)查看CPU缓存配置:了解CPU缓存的层次结构和大小,可以帮助分析缓存不命中的原因。

  • 可以使用lscpu命令来查看CPU的详细信息,包括缓存的大小和层次结构
  • 使用cat /proc/cpuinfo命令也可以获取到CPU的相关信息 lscpu | grep -E 'cache|CPU'
  • 工具如dmidecode可以提供更详细的硬件信息,包括CPU缓存配置(没看懂)

4)代码分析:通过性能分析工具(如gprof、Valgrind等)来分析代码,找出频繁导致缓存不命中的代码段。

5)系统监控:使用系统监控工具(如htop、vmstat等)来监控CPU和内存的使用情况,辅助分析缓存命中率。

你可能感兴趣的:(linux,运维,服务器)