1.CPU
1.1 CPU相关的术语
平均负载:单位时间内,系统处于可运行状态和不可中断状态的平均进程数,平均活跃进程数;和CPU使用率没直接关系。
CPU密集型进程,大量CPU使用会导致平均负载升高,此时CPU使用率也升高;
IO密集型进程,等待I/O会导致平均负载升高,此时CPU使用率不一定高;
大量等待CPU调度,会导致平均负载升高,此时CPU使用率也高;
可以用mpstat/pidstat工具辅助分析;
CPU上下文切换,按任务类型分为:
- 进程上下文切换;
- 线程上下文切换;
- 中断上下文切换;
切换的时机有:
- CPU时间片运行完,
- 系统资源不足导致进程挂起,
- 进程通过sleep主动挂起,
- 高优先级进程抢占时间片
- 硬件中断时cpu上的进程被挂起,转而执行内核的中断服务;
线程上下文切换:
1.前后线程属于同一个进程,切换时虚拟内存资源不变,只需要切换线程私有数据,寄存器等;
2.前后线程属于不同进程,与进程上下文切换相同
同进程的线程切换消耗资源较少。
中断上下文切换;
不涉及进程的切换,因此只需要包含内核态中断服务程序执行所必须的寄存器,内核堆栈,硬件中断参数等;
中断优先级比进程高,所以中断上下文切换和进程上下文切换不会同时发生。
vmstat可查看上下文切换;
- cs:每秒上下文切换次数;
- in:每秒中断次数;
- r:就绪队列长度,正在运行和等待cpu的进程数;
- b:blocked,处于不可中断睡眠状态的进程数;
查看单独某个进程情况:pidstat
pidstat -w 3
- cswch 每秒自愿上下文切换次数;(进程无法获取所需资源导致上下文切换)
- nvcswch: 每秒非自愿上下文切换次数;(时间片轮流等系统强制调度)
vmstat 1 1
- r列:远超系统cpu个数,说明存爱大量cpu竞争;
- us和sy列:sy列占比80%,说明cpu主要被内核栈用;
- in列:中断次数明显上升,说明中断处理也是潜在问题;
CPU使用率:除了空闲时间以为,其他进程占总CPU时间的百分比。
cat /proc/stat //计算cpu使用率;
也可以用tp/ps来查看一段时间内的平均值;
进程状态:
- R Running/Runnable, 表示进程在CPU的就绪队列中,正在运行或等待运行;
- D Disk Sleep,不可中断状态睡眠,一般表示进程正在跟硬件交互,并且交互进程中不允许被其他进程中断;
- Z Zombie,僵尸进程
- S InterruptibleSleep可中断睡眠状态,表示进程因为等待某个时间而被挂起,当等待事件发生则会被唤醒进入R状态;
- I Idle,空闲状态,用在不可中断睡眠的内核线程上。该状态不会导致平均负载升高;
- T Stop/Traced,表示进程处于暂停或跟踪状态;
- X Dead,进程死亡,不会在top/ps看到;
案例:
top查看,发现:
1)平均负载逐渐增加,且一分钟内平均负载达到cpu个数,说明系统可能已经有了性能瓶颈;
2)僵死进程较多且不断增加;
3)us/sys CPU使用率都不高,iowait比较高;
4)每个进程CPU使用率也不高,但又有两个进程处于D状态,可能在等待io;
分析数据可知,iowait 过高导致系统平均负载升高,僵尸进程不断增长说明有程序没能正确清理子进程资源;
用pidstat分析,
pidstat -d -p xxx
展示进程的I/o统计数据;
最终定位是app内部进行了磁盘的直接I/O,定位到具体代码,进行优化即可。
碰到iowait升高时,先用dstat pidstat等工具确认是否存在磁盘I/O问题,再找是哪些进程导致I/O,不能用strace直接分析进程调用时可以通过perf工具分析;
对于僵尸问题,用pstree找到父进程,然后看源码检查子进程结束的梳理逻辑即可。
1.2 CPU性能指标:
CPU使用率:用户CPU使用率,系统CPU使用率,等待I/O的CPU使用率;软/硬件中断CPU使用率;
steal CPU/guest CPU,表示虚拟机占用的CPU百分比;
平均负载: 理想情况下平均负载等于逻辑CPU个数,表示每个CPU充分利用,若大于说明系统负载较重;
进程上下文切换:
过多的切换,CPU时间消耗在上下文保护切换上;
CPU缓存命中率: 命中率越高,性能越好。L1/L2常用在单核,L3则用在多核;
1.3 性能分析工具:
平均负载案例:
先用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发现短时进程导致;
不可中断和僵尸进程案例
先用top观察iowait升高,发现大量不可中断和僵尸进程;
strace无法跟踪系统调用;
perf分析调用链发现根源来自磁盘直接i/o
软中断案例:
top观察系统软中断CPu使用率高;
查看/proc/softirqs找到变化率较快的几种软中断
sar命令发现是网络小包问题;
在生产环境中,往往没有权限安装新的工具包,只能最大化利用好系统中已经安装好的工具。
1.4 CPU优化
1.4.1 应用程序优化
- 编译器优化:编译阶段开启优化选项,比如gcc -O2;
- 算法优化;
- 异步处理:避免程序因为等待某个资源而一直阻塞,提升程序的并发处理能力,比如讲轮询改为时间通知;
- 多线程代替多进程:减少上下文切换成本;
- 善用缓存:提高cache命中率;
1.4.2 系统优化
- CPU绑定:将进程绑定到1个或多个CPu上,提高CPU缓存命中率,减少CPU调度带来的上下文切换;
- CPu独占:CPU亲和性机制来分配进程;
- 优先级调整:使用nice适当降低非核心应用的优先级;
- 为进程设置资源显示:cgroups设置使用上限,防止由某个应用自身问题耗尽系统资源;
- NUMA优化:CPu尽可能访问本地内存;
- 中断负载均衡:irqbalance,将中断处理过程自动负载均衡到各个CPU上
2.内存
安装bcc包可以通过cachestat和cachetop来检测缓存的读写命中情况;
Linux如何衡量内存资源是否紧张?
(1)直接内存回收:新的大块内存分配请求,但剩余内存不足,此时系统回收一部分内存;
(2)kswapd:内核线程定期回收内存,内核定义三个水位
pages_min,pages_low,pages_high;
(3)NUMA和SWAP:有时候系统剩余内存较多,但SWAP依旧升高,是由于处理器的NUMA架构;
swappiness
实际回收过程,根据/proc/sys/vm/swapiness选项来调整使用swap的积极度,从0-100,值越大,越积极使用swap,更倾向回收匿名页。否则倾向于回收文件页;
这里swapiness只是一个权重,即使设置为0,内存不够时,还是会发生swap;
2.2 内存性能指标
(1)系统内存指标
已用内存/剩余内存;
共享内存(tmpfs实现)
可用内存:包括剩余内存和可回收内存;
缓存:磁盘读取文件的页缓存,slab分配器中的可回收部分;
缓冲区:原始磁盘块的临时存储,缓存将要写入磁盘的数据;
(2)进程内存指标;
虚拟内存:
常驻内存:
共享内存:
swap内存:
(3)缺页异常
可以直接从物理内存中分配,次缺页异常;
需要磁盘IO介入(比如swap),主缺页异常,此时内存访问会慢很多;
2.3 内存性能工具
如何迅速分析内存的性能瓶颈?
通常先运行几个覆盖面较大的性能工具,比如 free,top,vmstat,pidstat等;
- 先用free和top查看系统整体内存使用情况;
- 再用vmstat和pidstat查看一段时间的趋势,判断内存问题类型;
- 最后进行详细分析,比如内存分配分析,缓存/缓冲区分析,具体内存使用分析等;
常见优化思路:
(1)最好禁止swap,若必须开启,则尽量降低swappiness的值;
(2)减少内存的动态分配,可以使用内存池,HugePage等;
(3)尽量使用缓存和缓冲区来访问数据。
(4)cgroups等方式限制进程的内存使用情况,确保系统内存不被异常内存耗尽;
(5)/proc/pid/oom_adj调整核心程序的oom_score,保证即使内存紧张,核心应用也不会被oom杀死;
vmstat使用详解:
https://www.cnblogs.com/ggjucheng/archive/2012/01/05/2312625.html
pidstat使用详解: