分析
- Linux平均负载表示可运行和正在运行的队列长度以及不可中断进程个数
- uptime
# uptime
15:41:50 up 62 days, 21:29, 1 user, load average: 0.51, 0.43, 0.40
- top
- vmstat:
- r表示正在运行或等待运行队列,
- b表示不可中断状态进程数
- us:用户态时间
- sy:系统态时间(内核)
- id:空闲
- wa:等待I/O,及线程被阻塞等待磁盘I/O时CPU空闲时间
- st: 偷取时间,CPU在虚拟化的环境下其他租户上的开销
# vmstat -w
procs -----------------------memory---------------------- ---swap-- -----io---- -system-- --------cpu--------
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 0 882408 2616 5561352 0 0 0 18 2 2 7 5 88 0 0
- mpstat:多处理器CPU统计
- %irq:硬件中断CPU用量
- %soft:软件中断CPU用量
# mpstat -P ALL 1
Linux 3.10.0-1160.6.1.el7.x86_64 (iZ2zeb9lhklwm0ado2pjwsZ) 08/12/2021 _x86_64_ (4 CPU)
04:00:23 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
04:00:24 PM all 29.75 0.00 4.50 3.75 0.00 0.25 0.00 0.00 0.00 61.75
04:00:24 PM 0 22.22 0.00 1.01 2.02 0.00 1.01 0.00 0.00 0.00 73.74
04:00:24 PM 1 25.00 0.00 2.00 1.00 0.00 1.00 0.00 0.00 0.00 71.00
04:00:24 PM 2 19.19 0.00 9.09 10.10 0.00 0.00 0.00 0.00 0.00 61.62
04:00:24 PM 3 51.00 0.00 6.00 3.00 0.00 0.00 0.00 0.00 0.00 40.00
- 历史CPU用量 sar
- -P ALL 输出各CPU使用量
- -u 输出平均CPU使用量
- -q 包含运行队列长度runq-sz(等待数加上运行数,与vmstat中的r相同)和平均负载
- 进程状态 ps aux
- pidstat 按进程或线程打印CPU用量
- -p ALL 打印所有进程,包含空闲进程
- -t 打印线程
- time 用来运行命令并报告CPU用量
$ time ls
dump.rdb logs
real 0m0.045s
user 0m0.001s
sys 0m0.002s
perf
- annotate 读取perf.data(由perf record创建)并显示注释过的代码
- evlist 列出一个perf.data文件里的事件名称
- record 运行一个命令,并把剖析信息记录在perf.data中
- report 读取perf.data并显示剖析信息
- sched 跟踪/测量调度器属性(延时)的工具
- script 读取perf.data并显示跟踪输出
- stat 运行一个命令并收集性能计数器统计信息
- top
- 系统剖析
perf record -a -g -F 997 sleep 10
perf report --stdio
- 进程剖析
perf record -g commend
- 调度器延时
perf sched record sleep 10
perf sched latency
-------------------------------------------------------------------------------------------------------------------------------------------
Task | Runtime ms | Switches | Avg delay ms | Max delay ms | Max delay start | Max delay end |
-------------------------------------------------------------------------------------------------------------------------------------------
runc:[2:INIT]:(22) | 4.263 ms | 22 | avg: 1.403 ms | max: 6.768 ms | max start: 5438093.891314 s | max end: 5438093.898082 s
nginx:(4) | 2946.288 ms | 22128 | avg: 0.038 ms | max: 17.533 ms | max at: 22252848.950345 s
ksoftirqd/3:24 | 289.859 ms | 16674 | avg: 0.034 ms | max: 10.897 ms | max at: 22252859.206264 s
sh:(2) | 5.145 ms | 12 | avg: 0.032 ms | max: 0.253 ms | max at: 22252864.076503 s
rcu_sched:9 | 168.639 ms | 13918 | avg: 0.031 ms | max: 8.001 ms | max at: 22252841.928397 s
php-fpm:(1180) | 36112.868 ms | 403985 | avg: 0.026 ms | max: 13.764 ms | max at: 22252850.055355 s
- 软件跟踪
- -e 跟踪事件,事件列表使用perf list获取
- page fault缺页异常分为两种类型,一种叫做major page fault,这种类型的缺页可以通过 Disk IO来满足,另一种叫做minor page fault,这种缺页可以直接利用内存中的缓存页满足。
# -e 跟踪上下文切换 perf record -g -a -e context-switches sleep 30 perf report --stdio
可视化 火焰图
概念
- CPU指令执行
- 指令预取
- 指令解码
- 执行
- 内存访问
- 寄存器写回
- 指令流水线是一种CPU架构,通过同时执行不同指令的不同部分,来达到同时执行多个指令的结果
- 指令宽度描述了同时处理的目标指令数量。现代处理器一般为宽度3或者宽度4,意味着它们可以在每个周期里最多完成3~4个指令
- 每指令周期数CPI:指令运行需要周期数。CPI较高代表CPU经常陷入停滞,通常 都是在访问内存。内存访问密集的负载,可以通过下面的方法提高性能,如何用更快的内存(DRAM)、提高内存本地性(软件配置),或者减少内存I/O数量。
- 使用率:CPU内核时间和用户时间
- 饱和度:队列长度
硬件
软件
-
调度器
- 分时:可运行线程之间的多任务,优先级执行最高优先级任务
- 抢占:一旦有高优先级线程变为可运行状态,调度器能够抢占当前运行的线程,这样较高优先级的线程可以马上开始运行
- 负载均衡:把可运行的线程移到空闲或者不繁忙的CPU队列中。
-
调度类:
- RT:为实时类负载提供固定的高优先级。内核支持用户和内核级别的抢占,允许RT任务以短延时分发。优先级范围为0~99
- O(1):O(1)调度器在Linux2.6作为默认用户进程分时调度器引入。名字来源于算法复杂度O(1)。
- CFS:完全公平调度,Linux2.6.23的默认分时调度器。这个调度器使用红黑树取代了传统运行队列来管理任务,以任务的CPU时间为键值。这样使得CPU的少量消费者相对于CPU消耗型负载更容易被找到,提高了交互和I/O消耗型负载的性能
-
调度器策略:用户级进程可以通过sched_setscheduler()设置调度器策略以调整调度类的行为。RT类支持SCHED_RR和SCHED_FIFO策略。而CFS类支持SCHED_NORMAL和SCHED_BATCH。
- RR:SCHED_RR是轮转调度。一旦一个线程用完了它的时间片,它就被挪到了自己优先级运行队列的尾部,这样同等优先级的其他线程可以运行
- FIFO:SCHED_FIFO是一种先进先出调度,一直运行队列头的线程直到它自愿退出,或者一个更高优先级的线程抵达。线程会一直运行,即便在运行队列当中存在相同优先级的其他进程
- NORMAL:SCHED_NORMAL(也称为SCHED_OTHER)是一种分时调度,是用户进程的默认策略。调度器根据调度类动态调整优先级。对于CFS,时间片是动态的。
- BATCH:SCHED_BATCH和SCHED_NORMAL类似,但期望线程是CPU消耗型的,这样就不会打断其他I/O消耗型交互工作。
基于资源容量规划
- 确定目标用户数或者应用程序请求频率
- 转化为每用户或每请求CPU使用率,对于现有系统,CPU用量可以通过监控获得,再除以现有用户数或请求数,对于未投入使用系统,负载生成工具可以模拟用户,以获得CPU用量
- 推算出当CPU资源达到100%使用率时的用户或者请求数,这就是系统理论上限
基准测试
- CPU指令:整数运算、浮点操作、内存加载和存储、分支和其他指令
- 内存访问:调查不同CPU缓存的延时和主存吞吐量
- 高级语言:类似CPU指令测试,不过使用高级解释或者编译语言编写
- 操作系统操作:测试CPU消耗性系统库和系统调用函数,例如getpid()和进程创建
- CPU基准测试工具 sysbench
# 8线程,最多计算100 000个质数
sysbench --threads=8 --cpu-max-prime=100000 cpu run
性能调优
- CPU绑定:把进程或线程绑定在单个CPU或一组CPU上,增加进程的CPU缓存温度,提高内存I/O性能
- 进程绑定:配置一个进程只跑在单个CPU上,或者预定义CPU组中的一个
- 独占CPU组:分出一组CPU,让这些CPU只能运行指定的进程。这可以更大地提升CPU缓存效率,因为当进程空闲时,其他进程不能使用CPU,保证了缓存的温度。
- Linux独占CPU组可以通过cpuset实现。
mkdir /dev/cpuset mount -t cpuset cpuset /dev/cpuset cd /dev/cpuset mkdir prodset # 创建一个叫prodset的cpuset cd prodset echo 7-10 >cpus # 分配7-10号cpu echo 1 > cpu_exclusive # 设置prodset为独有的exclusive echo 1159 > tasks # 分配PID 1159 到prodset
# 查看进程绑定,3表示11,两个cpu都可运行 taskset -p 35726 pid 35726's current affinity mask: 3 # 设置进程绑定第二个cpu,cpu是从0开始算的 taskset -pc 1 35726 pid 35726's current affinity list: 0,1 pid 35726's new affinity list: 1 # 启动程序时绑定进程到第二个cpu taskset -c 1 nginx
- 调度优先级
- 以nice19运行命令:nice -n 19 command
- renice 更改一个已经在运行进程的优先级
- Linux chrt命令可以显示并直接设置优先级和调度策略
资源控制
- cgroups