Linux性能优化-CPU
各种延时
CPU 性能指标
- CPU 使用率
- 用户 CPU 使用率, 包括用户态(user)和低优先级用户态(nice). 该指标过高说明应用程序比较繁忙.
- 系统 CPU 使用率, CPU 在内核态运行的时间百分比(不含中断). 该指标高说明内核比较繁忙.
- 等待 I/O 的 CPU 使用率, iowait, 该指标高说明系统与硬件设备 I/O 交互时间比较长.
- 软/硬中断 CPU 使用率, 该指标高说明系统中发生大量中断.
- steal CPU / guest CPU, 表示虚拟机占用的 CPU 百分比.
- 平均负载
- 理想情况下平均负载等于逻辑 CPU 个数,表示每个 CPU 都被充分利用. 若大于则说明系统负载较重.
- 进程上下文切换
- 包括无法获取资源的自愿切换和系统强制调度时的非自愿切换.
- 上下文切换本身是保证 Linux 正常运行的一项核心功能.
- 过多的切换则会将原本运行进程的 CPU 时间消耗在寄存器,内核占及虚拟内存等数据保存和恢复上
- CPU 缓存命中率
- CPU 缓存的复用情况,命中率越高性能越好. 其中 L1/L2 常用在单核,L3 则用在多核中
性能工具
- 平均负载案例
- 先用 uptime 查看系统平均负载
- 判断负载在升高后再用 mpstat 和 pidstat 分别查看每个 CPU 和每个进程 CPU 使用情况.找出导致平均负载较高的进程.
- 上下文切换案例
- 先用 vmstat 查看系统上下文切换和中断次数
- 再用 pidstat 观察进程的自愿和非自愿上下文切换情况
- 最后通过 pidstat 观察线程的上下文切换情况
- 进程 CPU 使用率高案例
- 先用 top 查看系统和进程的 CPU 使用情况,定位到进程
- 再用 perf top 观察进程调用链,定位到具体函数
- 系统 CPU 使用率高案例
- 先用 top 查看系统和进程的 CPU 使用情况,top/pidstat 都无法找到 CPU 使用率高的进程
- 重新审视 top 输出
- 从 CPU 使用率不高,但是处于 Running 状态的进程入手
- perf record/report 发现短时进程导致 (execsnoop 工具)
- 不可中断和僵尸进程案例
- 先用 top 观察 iowait 升高,发现大量不可中断和僵尸进程
- strace 无法跟踪进程系统调用
- perf 分析调用链发现根源来自磁盘直接 I/O
- 软中断案例
- top 观察系统软中断 CPU 使用率高
- 查看/proc/softirqs 找到变化速率较快的几种软中断
- sar 命令发现是网络小包问题
- tcpdump 找出网络帧的类型和来源,确定 SYN FLOOD 攻击导致
根据不同的性能指标来找合适的工具:
为了缩小排查范围,我通常会先运行几个支持指标较多的工具,如 top、vmstat 和 pidstat 。看看下面三者的关系:
平均负载和 CPU 使用率
平均负载
平均负载是指单位时间内,系统处于可运行状态(包括正在运行)和不可中断状态的平均进程数,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系。
当平均负载高于 CPU 数量 70% 的时候,你就应该分析排查负载高的问题了。
CPU 使用率
CPU 使用率,是单位时间内 CPU 繁忙情况的统计,跟平均负载并不一定完全对应。
CPU 使用率描述了非空闲时间占总 CPU 时间的百分比,根据 CPU 上运行任务的不同,又被分为用户 CPU、系统 CPU、等待 I/O CPU、软中断和硬中断等。
- CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者是一致的;
- I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;
- 大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。
排查步骤
|
|
- 如果%usr 和%nice 比较高,%iowait 比较低则表明是 CPU 密集型
- 如果%usr 和%nice 比较低,%iowait 比较高则表明是 IO 密集型
- 如果%usr 和%nice 比较低,%iowait 比较低但是%wait 比较高说明进程太多了
上下文切换
CPU 的上下文切换就可以分为几个不同的场景,也就是进程上下文切换、线程上下文切换以及中断上下文切换。
由于上下文切换需要陷入内核,所以上下文切换属于系统 CPU 使用率。
根据上下文切换的类型,再做具体分析。
- 自愿上下文切换变多了,说明进程都在等待资源,有可能发生了 I/O、内存等其他问题;
- 非自愿上下文切换变多了,说明进程都在被强制调度,也就是都在争抢 CPU,说明 CPU 的确成了瓶颈;
- 中断次数变多了,说明 CPU 被中断处理程序占用,还需要通过查看 /proc/interrupts 文件来分析具体的中断类型。
|
|
具体某个应用 CPU 飙高
碰到 CPU 使用率升高的问题,你可以借助 top、pidstat 等工具,确认引发 CPU 性能问题的来源;
- 用户(%user) CPU 和 Nice(%nice) CPU 高,说明用户态进程占用了较多的 CPU,所以应该着重排查进程的性能问题。
- 系统(%system) CPU 高,说明内核态占用了较多的 CPU,所以应该着重排查内核线程或者系统调用的性能问题。
- I/O(%iowait) 等待 CPU 高,说明等待 I/O 的时间比较长,所以应该着重排查系统存储是不是出现了 I/O 问题。
- 软中断(%softirq)和硬中断(%irq)高,说明软中断或硬中断的处理程序占用了较多的 CPU,所以应该着重排查内核中的中断服务程序。
再使用 perf 等工具,排查出引起性能问题的具体函数。
|
|
CPU 使用率整体高,但各个应用使用率都很低
碰到常规问题无法解释的 CPU 使用率情况时,首先要想到有可能是短时应用导致的问题,比如有可能是下面这两种情况。
- 应用里直接调用了其他二进制程序,这些程序通常运行时间比较短,通过 top 等工具也不容易发现。
- 应用本身在不停地崩溃重启,而启动过程的资源初始化,很可能会占用相当多的 CPU。
对于这类进程,我们可以用 pstree 或者 execsnoop 找到它们的父进程,再从父进程所在的应用入手,排查问题的根源。
iowait 高
碰到 iowait 升高时,需要先用 dstat、pidstat 等工具,确认是不是磁盘 I/O 的问题,然后再找是哪些进程导致了 I/O。
等待 I/O 的进程一般是不可中断状态,所以用 ps 命令找到的 D(Disk Sleep) 状态(即不可中断状态)的进程,多为可疑进程。
- 可以用 strace -p [pid] 直接分析这个进程的系统调用。
- strace 没查到可使用 perf record -g 记录,perf report 再输出报告
僵尸进程
僵尸进程表示进程已经退出,但它的父进程还没有回收子进程占用的资源。短暂的僵尸状态我们通常不必理会,但进程长时间处于僵尸状态,就应该注意了,可能有应用程序没有正常处理子进程的退出。
使用 pstree 找出父进程后,去查看父进程的代码,检查 wait() / waitpid() 的调用,或是 SIGCHLD 信号处理函数的注册就行了。
|
|
中断
中断是系统用来响应硬件设备请求的一种机制,它会打断进程的正常调度和执行,然后调用内核中的中断处理程序来响应设备的请求。
Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部:
- 上半部用来快速处理中断,也就是我们常说的硬中断,它在中断禁止模式下运行,主要处理跟硬件紧密相关的或时间敏感的工作。
- 下半部则是由内核触发,也就是我们常说的软中断,下半部用来延迟处理上半部未完成的工作,通常以内核线程的方式运行。
上半部会打断 CPU 正在执行的任务,然后立即执行中断处理程序。而下半部以内核线程的方式执行,并且每个 CPU 都对应一个软中断内核线程,名字为 “ksoftirqd/CPU 编号”,比如说, 0 号 CPU 对应的软中断内核线程的名字就是 ksoftirqd/0。
软中断不只包括了刚刚所讲的硬件设备中断处理程序的下半部,一些内核自定义的事件也属于软中断,比如网络收发、定时、内核调度和 RCU 锁(Read-Copy Update 的缩写,RCU 是 Linux 内核中最常用的锁之一)等。
|
|
软中断 CPU 使用率(softirq)升高是一种很常见的性能问题。虽然软中断的类型很多,但实际生产中,我们遇到的性能瓶颈大多是网络收发类型的软中断,特别是网络接收的软中断。
在碰到这类问题时,你可以借用 sar、tcpdump 等工具,做进一步分析。
|
|