1 理解CPU平均负载
啥是CPU平均负载呢?
日常运维我们常用uptime或top命令查看系统当前负载,也可以使用cat /proc/loadavg
严肃点说平均负载是指:某段时间内,内核标记为可运行状态或不可中断状态的平均进程数。
可运行状态:正在使用CPU或等待CPU,即R状态进程(Running或Runnable)
不可中断状态:等待某种资源可用(通常是I/O),即D状态进程(不含wait状态)
具体算法在/usr/src/kernels/${内核版本}/include/linux/sched.h 函数CALC_LOAD(load,exp,n)
打个比方
以单核CPU为例,单核CPU就像一条单行隧道,每个进程是行驶的小汽车。
Load=0 隧道无车
Load=0.5 隧道有车不多,顺畅
Load=1.0 隧道满载,整齐不拥塞
Load=1.7 隧道过载,有车等待塞车
我们不禁发问 平均负载究竟多少比较合理?
原理上讲对于多核CPU,负载均值是基于CPU逻辑核数决定的;参考同胞经验值,一般认为单个核心负载0.7是警戒线,例如16核警戒线为16*0.7=11.2
实际业务对CPU需求各不相同,有些业务系统常年低负载/高负载,比较合理的做法是分析历史负载数据和趋势变化设置警戒线
综合分析最近1/5/15分钟系统平均负载,如果三个值相近则说明系统平稳;如果最近1分钟负载大、最近15分钟负载小,则可能只是短暂业务波峰
2 理解CPU使用率
看完CPU负载,咱接着捣鼓下CPU使用率又是啥?
先敲下top命令瞅瞅
CPU使用率(算法)是指:单位时间内CPU繁忙情况,可以通过/proc/stat来计算
CPU行数据说明(以cpu第一行为例)
user[1028] : 用户态的CPU时间(单位:jiffies = 0.01秒) ,不包含 nice值为负进程
nice[103] : 低优先级用户态 CPU 时间,也就是进程的 nice 值被调整为 1-19 之间时的 CPU 时间。这里注意,nice 可取值范围是 -20 到 19,数值越大,优先级反而越低。
system[2818]: 内核态时间
idle[1172970]: 除IO等待时间以外其它等待时间
iowait[135] : IO等待时间
irq[0]: 处理硬中断时间
softirq[25]: 处理软中断时间
steal[0]:当系统运行在虚拟机时,被其他虚拟机抢占的CPU时间
guest[0]:虚拟化运行其他操作系统的时间,也就是运行虚拟机的 CPU 时间
guest_nice[0]:以低优先级运行虚拟机的时间
CPU时间=user+system+nice+idle+iowait+irq+softirq
[intr]:第一个值为自系统启动以来,发生的所有的中断的次数;然后每个数对应一个特定的中断自系统启动以来所发生的次数。
[ctxt]:系统启动以来CPU发生的上下文交换的次数。
[btime]:系统启动到现在为止的时间,单位为秒。
[processes (total_forks)]:系统启动以来所创建的任务的个数目。
[procs_running]:当前运行队列的任务的数目。
[procs_blocked]:当前被阻塞的任务的数目。
Linux进程运行又分用户态和内核态。CPU使用率通常是指:CPU执行非系统空闲进程的时间/CPU总的执行时间,公式如下:
计算CPU使用率脚本参考 https://blog.51cto.com/13466287/2349823
看了这么多枯燥的文字,我们想知道CPU平均负载和CPU使用率到底有没有联系?
上文提到平均负载统计的是处于可运行状态和不可中断状态的进程数。这包括正在使用CPU的,等待使用CPU的和等待某种资源(比如I/O)的进程。
从进程特点看:
CPU密集型进程,会大量真实占用CPU时间分片,负载和使用率均高;
IO密集型进程,平均负载高(等待IO资源),而使用率不一定高
举个例子:假设某个计算进程,运行期间CPU使用率100%,执行单个进程时,负载1,CPU使用率100%;同时执行2个进程时,负载2,CPU使用率仍100%(需要在不同进程间切换,仅为方便理解、实际切换也有开销)。
原来平均负载和使用率没有必然联系,平均负载高可能只是等待繁忙的I/O,可以使用top、ps、pidstat等命令来排查定位。CPU使用率除了进程自身消耗(用户态、内核态),还包括对软硬中断处理、上下文切换、等待IO资源等。
3 CPU使用率过高分析
线上CPU使用率/负载飙升,通过top、pidstat等命令一般可以快速定位到进程。那么如何进一步分析是哪段函数 或者哪些系统调用引起的呢?
Linux上进程追踪和调试常见有gdb, strace, perf等等。
(1) GDB调试时经常需要中断程序执行(断点),以查看执行和上下文,对于线上作业难以接受;(2) strace和perf都支持运行时追踪。perf已经成为linux内置性能分析工具,相比strace功能更完善。
perf小试牛刀
# 通过top定位到PID=17985# perf top –g –p 17985
# 可以通过yum install perf直接安装
可以追踪指定已运行进程的调用关系,最终定位到进程、函数段。
perf + FlameGraph还能生成火焰图,更直观、交互的分析程序性能
详细参考 http://www.brendangregg.com/flamegraphs.html
来左边跟我一起画个龙,在你终端画一道火焰红!想不到还能如此酷炫吧!
4 CPU优化常见方法
经过层层剖析,最终定位到性能问题的瓶颈后,理了下思路,觉得不应该急着操作:
首先明确是硬件问题,还是软件问题,比如CPU是否开了节能模式、是否被锁频?IO慢导致iowait满载,通过更换高速硬盘、阵列缓存、程序内存缓冲区是否可以解决?而不是上来就动刀子;软件问题也需要针对应用程序排查日志、性能分析;
性能问题通常彼此关联,可能同时暴露多个性能问题,需要我们抓住核心矛盾;一个水桶无论多高,它盛水的高度取决于其中最低的那块木板;
实际优化以业务指标为导向,业务角度关注请求延迟、并发数等指标;运维角度关注CPU负载、使用率等指标!优化前后做好指标的量化和对比。
回到CPU负载高本身,我们也从前辈处GET到一些切实可行的软优化手段:
优化中断:默认软中断由cpu0处理,通过启用irqbalance服务 或 配置smp_affinity,将中断分散到多个cpu核心上,比如针对网卡软中断优化;
cpu绑定:将进程绑定到一个或者多个指定核上,提高cpu缓存命中率,减少上下文切换,最常见的是nginx cpu绑定
nice调整:调整进程的nice值,提高核心业务进程的CPU优化级
CGroup:基于内核cgroup功能来配额资源,包括CPU、内存等
Numa优化:多CPU架构中,BIOS开启numa后,使用numactl来优化内存分配,让CPU尽可能只访问本地内存