基本概念
进程(process)和处理器(processor)
进程是一个OS抽象的概念,是用来执行程序的环境,包括内存地址空间、文件描述符、线程栈和寄存器。
处理器是系统插槽或处理器板上的物理芯片,以核或硬件线程的方式包含了一块或多块CPU。
硬件线程
一种支持在一个核上同时运行多个线程的CPU架构,每个线程是一个独立的CPU实例。
运行队列
一个等待CPU服务的可运行线程队列。
用户态时间和内核态时间
CPU花在执行用户态应用程序代码的时间成为用户态时间。
执行内核态代码的时间成为内核态时间,包括系统调用、内核线程和中断时间。
CPI
指令周期数,表示执行每个指令所花费的CPU时钟周期数
CPU的使用率和饱和度
使用率是一段时间内CPU实例忙于执行工作的比例,CPU使用率通常分为内核时间和用户时间两个指标。
饱和度一个使用率100%的CPU被称为饱和的。
指令流水线如果提高CPU吞吐量
指令流水线是一种CPU架构,通过同时执行不同指令的不同部分,来达到同时执行多个指令,类似工厂的组装线,生产的每个步骤都可以同时执行,提高了吞吐量。
指令宽度如何提高CPU吞吐量
指令宽度同时处理多个目标指令。通常和指令流水线一起使用达到高指令吞吐量
多进程和多线程模型的优点
多进程优点:
开发简单;
多线程优点:
内存开销小,CPU开销小,通信快。
没有任务可运行时,CPU会做什么
在没有任务可运行时执行空闲线程,它通常被设计为通知CPU执行停止或者减速以节省资源。CPU会在下一次硬件中断醒来。
USE法
- 利用率
- 每个CPU:mpstat -P ALL,%idle; sar -P ALL,%idle;
- 系统范围:vmstat 1,id项;sar -u %idle项;dstat -c, idl项
- 每个进程:top ,%CPU项; htop,CPU%项;ps -o pcpu; pidstat 1,%CPU项
- 每个内核线程:top/htop(按k转换显示),找到VIRT==0(启发式)
- 饱和度
- 系统范围:vmstat 1,r>CPU数量;sar -q,runq-sz>CPU数量;dstat -p ,run>CPU数量
- 每个进程:/proc/PID/shedstat 第二项(shed_info.run_delay);
perf sched latency(显示每次调度的平均和最大延时);
动态跟踪,如SystemTap中schedtimes.stp.queue(us)
- 错误
- 处理器特定错误事件,可以用perf(LPE)
分析工具
uptime
分析系统平均负载
$ uptime
11:51:24 up 26 days, 18:09, 3 users, load average: 1.61, 0.66, 0.43
分别统计1/5/15分钟内的平均负载。通过这三个数字可以判断15分钟内负载是上升还是下降还是平稳。平均负载大于CPU数量表示CPU不足以服务线程。
linux把不可中断状态执行磁盘IO的任务也计入平均负载,平均负载不再能准确表示CPU余量或饱和度。
在linux上最好通过vmstat、mpstat来评估
vmstat
虚拟内存统计命令,最后几列打印了系统全局范围的CPU平均负载:
$ vmstat 1
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 4893512 1132 9763328 0 0 0 11 1 2 2 1 97 0 0
0 0 0 4893356 1132 9763332 0 0 0 57 4063 7094 1 2 97 0 0
0 0 0 4893092 1132 9763336 0 0 0 80 7493 11883 3 4 94 0 0
0 0 0 4893232 1132 9763336 0 0 0 12 4911 8364 2 2 96 0 0
0 0 0 4893200 1132 9763348 0 0 0 115 4952 8509 2 2 97 0 0
0 0 0 4893076 1132 9763348 0 0 0 44 4176 7167 1 2 96 0 0
r:可运行线程总数;
us:用户态时间;
sy:系统态时间;
id:空闲时间;
wa:IO等待;
st:偷取,CPU在虚拟化的环境下在其它租户上的花销。
mpstat
多处理器统计信息工具mpstat,能报告每个CPU的信息。
$ mpstat -P ALL 1
Linux 3.10.0-957.1.3.el7.x86_64 (k8snode-4) 02/18/2019 _x86_64_ (8 CPU)
02:43:06 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
02:43:07 PM all 0.12 0.00 0.12 0.00 0.00 0.00 0.00 0.00 0.00 99.75
02:43:07 PM 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
02:43:07 PM 1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
02:43:07 PM 2 1.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 99.00
02:43:07 PM 3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
02:43:07 PM 4 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
02:43:07 PM 5 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
02:43:07 PM 6 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
02:43:07 PM 7 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
..........
CPU:逻辑CPU ID,或者all表示总信息;
%usr:用户态时间;
%nice:以nice优先级运行的进程用户态时间;
%sys:系统态时间;
%iowait:IO等待;
%irq:硬件中断CPU用量;
%soft:软件中断CPU用量;
%steal:耗费在服务其他租户的时间;
%guest:花在访客虚拟机的时间;
%idle:空闲。
sar
系统活动报告器
从零点起到现在的所有活动报告,没隔10分钟取一次。最后还有平均值。
sar -P ALL
$ sar -P ALL
Linux 3.10.0-957.1.3.el7.x86_64 (k8snode-4) 02/18/2019 _x86_64_ (8 CPU)
12:00:01 AM CPU %user %nice %system %iowait %steal %idle
12:10:01 AM all 2.95 0.02 1.72 0.02 0.00 95.30
12:10:01 AM 0 2.77 0.01 1.60 0.01 0.00 95.61
12:10:01 AM 1 3.13 0.01 1.83 0.04 0.00 94.99
12:10:01 AM 2 3.13 0.02 1.83 0.02 0.00 95.01
12:10:01 AM 3 3.02 0.01 1.78 0.02 0.00 95.17
12:10:01 AM 4 3.15 0.02 1.64 0.01 0.00 95.18
12:10:01 AM 5 2.80 0.01 1.87 0.01 0.00 95.31
12:10:01 AM 6 2.76 0.02 1.57 0.01 0.00 95.64
12:10:01 AM 7 2.86 0.02 1.60 0.02 0.00 95.51
12:10:01 AM CPU %user %nice %system %iowait %steal %idle
12:20:01 AM all 2.96 0.02 1.72 0.02 0.00 95.29
12:20:01 AM 0 2.62 0.02 1.62 0.01 0.00 95.73
12:20:01 AM 1 3.10 0.02 1.82 0.03 0.00 95.04
12:20:01 AM 2 3.17 0.02 1.83 0.02 0.00 94.97
12:20:01 AM 3 3.24 0.02 1.73 0.02 0.00 94.99
12:20:01 AM 4 2.75 0.02 1.76 0.01 0.00 95.47
12:20:01 AM 5 2.87 0.02 1.84 0.01 0.00 95.26
12:20:01 AM 6 2.94 0.02 1.64 0.02 0.00 95.38
........
Average: CPU %user %nice %system %iowait %steal %idle
Average: all 3.22 0.02 1.95 0.03 0.00 94.78
Average: 0 2.96 0.02 1.81 0.02 0.00 95.19
Average: 1 3.49 0.02 2.12 0.04 0.00 94.34
Average: 2 3.54 0.02 2.09 0.03 0.00 94.32
Average: 3 3.27 0.02 1.97 0.04 0.00 94.70
Average: 4 3.31 0.02 1.92 0.04 0.00 94.72
Average: 5 3.05 0.02 2.10 0.03 0.00 94.81
Average: 6 3.05 0.02 1.82 0.03 0.00 95.08
Average: 7 3.10 0.02 1.81 0.03 0.00 95.04
sar -u
$ sar -u
Linux 3.10.0-957.1.3.el7.x86_64 (k8snode-4) 02/18/2019 _x86_64_ (8 CPU)
12:00:01 AM CPU %user %nice %system %iowait %steal %idle
12:10:01 AM all 2.95 0.02 1.72 0.02 0.00 95.30
12:20:01 AM all 2.96 0.02 1.72 0.02 0.00 95.29
12:30:01 AM all 2.95 0.01 1.73 0.02 0.00 95.29
12:40:02 AM all 2.95 0.02 1.72 0.02 0.00 95.29
12:50:01 AM all 2.97 0.02 1.78 0.02 0.00 95.21
01:00:01 AM all 2.95 0.01 1.72 0.02 0.00 95.29
01:10:01 AM all 3.06 0.02 1.76 0.02 0.00 95.14
01:20:01 AM all 2.94 0.02 1.72 0.01 0.00 95.31
01:30:01 AM all 2.93 0.02 1.72 0.01 0.00 95.32
01:40:01 AM all 2.94 0.02 1.68 0.02 0.00 95.35
01:50:01 AM all 2.94 0.01 1.71 0.01 0.00 95.32
02:00:02 AM all 2.96 0.01 1.72 0.01 0.00 95.29
02:10:01 AM all 2.92 0.02 1.73 0.01 0.00 95.32
02:20:01 AM all 2.92 0.01 1.72 0.02 0.00 95.34
02:30:01 AM all 2.94 0.02 1.72 0.02 0.00 95.31
......
Average: all 3.22 0.02 1.96 0.03 0.00 94.77
sar -q展示包括运行队列runq-sz(等待数+运行数)和平均负载。
$ sar -q
Linux 3.10.0-957.1.3.el7.x86_64 (k8snode-4) 02/18/2019 _x86_64_ (8 CPU)
12:00:01 AM runq-sz plist-sz ldavg-1 ldavg-5 ldavg-15 blocked
12:10:01 AM 1 1085 0.24 0.32 0.33 0
12:20:01 AM 2 1087 0.24 0.29 0.31 0
12:30:01 AM 2 1085 0.10 0.22 0.26 0
12:40:02 AM 2 1084 0.14 0.19 0.22 0
12:50:01 AM 1 1087 0.16 0.32 0.28 0
01:00:01 AM 3 1085 0.21 0.32 0.31 0
01:10:01 AM 2 1086 0.12 0.21 0.27 0
01:20:01 AM 1 1087 0.11 0.32 0.31 0
01:30:01 AM 4 1084 0.15 0.16 0.24 0
01:40:01 AM 3 1085 0.05 0.16 0.21 0
01:50:01 AM 1 1085 0.19 0.16 0.18 0
02:00:02 AM 3 1084 0.10 0.14 0.15 0
02:10:01 AM 1 1085 1.50 0.91 0.49 0
02:20:01 AM 5 1087 0.21 0.36 0.41 0
02:30:01 AM 1 1085 0.36 0.60 0.51 0
02:40:01 AM 1 1085 0.16 0.35 0.43 0
02:50:01 AM 1 1085 0.03 0.18 0.31 0
03:00:01 AM 4 1086 0.29 0.25 0.30 0
03:10:02 AM 3 1085 1.12 0.60 0.42 0
03:20:01 AM 1 1086 0.10 0.39 0.45 0
03:30:01 AM 1 1087 1.90 1.34 0.82 0
03:40:01 AM 1 1084 0.58 1.27 1.13 0
03:50:01 AM 2 1084 0.21 0.51 0.81 0
04:00:01 AM 3 1086 0.55 0.40 0.59 0
04:10:01 AM 1 1088 0.11 0.20 0.40 0
.........
12:30:01 PM runq-sz plist-sz ldavg-1 ldavg-5 ldavg-15 blocked
12:40:01 PM 2 1121 0.62 0.59 0.53 0
12:50:01 PM 1 1087 0.81 0.53 0.51 0
01:00:01 PM 2 1087 1.50 0.76 0.58 0
01:10:01 PM 1 1083 0.42 0.46 0.51 0
01:20:01 PM 1 1092 0.55 0.61 0.55 0
01:30:02 PM 2 1086 0.04 0.20 0.36 0
01:40:01 PM 1 1087 0.33 0.26 0.30 0
01:50:01 PM 3 1086 0.47 0.47 0.40 0
02:00:01 PM 2 1089 0.10 0.21 0.30 0
02:10:01 PM 1 499 0.11 0.17 0.26 0
02:20:01 PM 2 584 0.40 0.27 0.28 0
02:30:01 PM 2 952 0.58 0.67 0.49 0
02:40:01 PM 2 529 0.35 0.46 0.49 0
02:50:01 PM 1 539 0.28 0.27 0.36 0
03:00:02 PM 1 977 0.36 0.49 0.44 0
Average: 2 1057 0.42 0.42 0.42 0
ps
$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 194500 7396 ? Ss Jan22 3:34 /usr/lib/systemd/systemd --system --deserialize 17
root 2 0.0 0.0 0 0 ? S Jan22 0:01 [kthreadd]
root 3 0.0 0.0 0 0 ? S Jan22 0:24 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S< Jan22 0:00 [kworker/0:0H]
root 7 0.0 0.0 0 0 ? S Jan22 0:27 [migration/0]
root 8 0.0 0.0 0 0 ? S Jan22 0:00 [rcu_bh]
root 9 0.0 0.0 0 0 ? S Jan22 37:49 [rcu_sched]
root 10 0.0 0.0 0 0 ? S< Jan22 0:00 [lru-add-drain]
........
展示CPU信息的主要列为%CPU和TIME;
TIME:显示进程自创建开始消耗的CPU总时间(用户态+系统态),格式:小时:分:秒;
%CPU:显示前一秒所有的CPU使用量之和,一个单线程的CPU型进程会显示100%,一个双线程的CPU型进程会显示200%.
top
$ top
top - 15:24:52 up 26 days, 21:42, 3 users, load average: 0.16, 0.30, 0.38
Tasks: 302 total, 1 running, 301 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.5 us, 4.9 sy, 0.0 ni, 94.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 16431008 total, 4777096 free, 1825584 used, 9828328 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 13495344 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4439 root 20 0 10.1g 90176 25484 S 4.8 0.5 1:05.45 etcd
9735 root 20 0 1371032 105444 40844 S 4.8 0.6 1:54.15 kubelet
pidstat
按进程或线程打印CPU用量,默认仅循环输出活动线程的信息。
$ pidstat 1
Linux 3.10.0-957.1.3.el7.x86_64 (k8snode-4) 02/18/2019 _x86_64_ (8 CPU)
03:28:57 PM UID PID %usr %system %guest %CPU CPU Command
03:28:58 PM 0 9 0.00 0.94 0.00 0.94 7 rcu_sched
03:28:58 PM 0 34 0.00 0.94 0.00 0.94 5 ksoftirqd/5
03:28:58 PM 0 4439 0.94 0.94 0.00 1.89 0 etcd
03:28:58 PM 42 6739 0.94 0.00 0.00 0.94 5 gsd-color
03:28:58 PM 0 8607 1.89 1.89 0.00 3.77 1 kube-apiserver
03:28:58 PM 0 8726 0.00 0.94 0.00 0.94 0 kube-scheduler
03:28:58 PM 0 9735 1.89 0.00 0.00 1.89 3 kubelet
03:28:58 PM 0 10507 0.00 0.94 0.00 0.94 2 coredns
03:28:58 PM 0 11715 0.00 1.89 0.00 1.89 7 calico-node
03:28:58 PM 1000 15589 0.94 2.83 0.00 3.77 1 pidstat
03:28:58 PM 1000 15982 0.00 0.94 0.00 0.94 7 netchecker-agen
03:28:58 PM 0 32733 0.94 0.00 0.00 0.94 6 dockerd
........
pidstat -p ALL打印所有进程包括空闲进程
$ pidstat -p ALL
Linux 3.10.0-957.1.3.el7.x86_64 (k8snode-4) 02/18/2019 _x86_64_ (8 CPU)
03:34:20 PM UID PID %usr %system %guest %CPU CPU Command
03:34:20 PM 0 1 0.00 0.01 0.00 0.01 2 systemd
03:34:20 PM 0 2 0.00 0.00 0.00 0.00 7 kthreadd
03:34:20 PM 0 3 0.00 0.00 0.00 0.00 0 ksoftirqd/0
03:34:20 PM 0 5 0.00 0.00 0.00 0.00 0 kworker/0:0H
03:34:20 PM 0 7 0.00 0.00 0.00 0.00 0 migration/0
03:34:20 PM 0 8 0.00 0.00 0.00 0.00 5 rcu_bh
03:34:20 PM 0 9 0.00 0.10 0.00 0.10 5 rcu_sched
pidstat -t打印每个线程
$ pidstat -t
Linux 3.10.0-957.1.3.el7.x86_64 (k8snode-4) 02/18/2019 _x86_64_ (8 CPU)
03:35:55 PM UID TGID TID %usr %system %guest %CPU CPU Command
03:35:55 PM 0 1 - 0.00 0.01 0.00 0.01 1 systemd
03:35:55 PM 0 - 1 0.00 0.01 0.00 0.01 1 |__systemd
03:35:55 PM 0 2 - 0.00 0.00 0.00 0.00 7 kthreadd
03:35:55 PM 0 - 2 0.00 0.00 0.00 0.00 7 |__kthreadd
03:35:55 PM 0 3 - 0.00 0.00 0.00 0.00 0 ksoftirqd/0
03:35:55 PM 0 - 3 0.00 0.00 0.00 0.00 0 |__ksoftirqd/0
03:35:55 PM 0 7 - 0.00 0.00 0.00 0.00 0 migration/0
03:35:55 PM 0 - 7 0.00 0.00 0.00 0.00 0 |__migration/0
03:35:55 PM 0 9 - 0.00 0.10 0.00 0.10 0 rcu_sched
03:35:55 PM 0 - 9 0.00 0.10 0.00 0.10 0 |__rcu_sched
03:35:55 PM 0 11 - 0.00 0.00 0.00 0.00 0 watchdog/0
03:35:55 PM 0 - 11 0.00 0.00 0.00 0.00 0 |__watchdog/0
03:35:55 PM 0 12 - 0.00 0.00 0.00 0.00 1 watchdog/1
03:35:55 PM 0 - 12 0.00 0.00 0.00 0.00 1 |__watchdog/1
time
time可以用来运行命令并报告CPU用量
#可以计算文件校验码并显示所用的CPU用量,该命令执行两次,会发现所用的时间第二次更少,可能是由于第一次存在磁盘io等待,第二次使用了缓存
time cksum xxx.iso
DTrace&SystemTap
DTrace相对于mpstat等工具,可以跟踪更加详细的信息,如内核具体在做什么等。
SystemTap适用于linux系统的跟踪工具。
perf
linux性能事件,是一整套剖析和跟踪工具。
perf --help之后可以看到perf的二级命令。
序号 | 命令 | 作用 |
---|---|---|
1 | annotate | 解析perf record生成的perf.data文件,显示被注释的代码。 |
2 | archive | 根据数据文件记录的build-id,将所有被采样到的elf文件打包。利用此压缩包,可以再任何机器上分析数据文件中记录的采样数据。 |
3 | bench | perf中内置的benchmark,目前包括两套针对调度器和内存管理子系统的benchmark。 |
4 | buildid-cache | 管理perf的buildid缓存,每个elf文件都有一个独一无二的buildid。buildid被perf用来关联性能数据与elf文件。 |
5 | buildid-list | 列出数据文件中记录的所有buildid。 |
6 | diff | 对比两个数据文件的差异。能够给出每个符号(函数)在热点分析上的具体差异。 |
7 | evlist | 列出数据文件perf.data中所有性能事件。 |
8 | inject | 该工具读取perf record工具记录的事件流,并将其定向到标准输出。在被分析代码中的任何一点,都可以向事件流中注入其它事件。 |
9 | kmem | 针对内核内存(slab)子系统进行追踪测量的工具 |
10 | kvm | 用来追踪测试运行在KVM虚拟机上的Guest OS。 |
11 | list | 列出当前系统支持的所有性能事件。包括硬件性能事件、软件性能事件以及检查点。 |
12 | lock | 分析内核中的锁信息,包括锁的争用情况,等待延迟等。 |
13 | mem | 内存存取情况 |
14 | record | 收集采样信息,并将其记录在数据文件中。随后可通过其它工具对数据文件进行分析。 |
15 | report | 读取perf record创建的数据文件,并给出热点分析结果。 |
16 | sched | 针对调度器子系统的分析工具。 |
17 | script | 执行perl或python写的功能扩展脚本、生成脚本框架、读取数据文件中的数据信息等。 |
18 | stat | 执行某个命令,收集特定进程的性能概况,包括CPI、Cache丢失率等。 |
19 | test | perf对当前软硬件平台进行健全性测试,可用此工具测试当前的软硬件平台是否能支持perf的所有功能。 |
20 | timechart | 针对测试期间系统行为进行可视化的工具 |
21 | top | 类似于linux的top命令,对系统性能进行实时分析。 |
22 | trace | 关于syscall的工具。 |
23 | probe | 用于定义动态检查点。 |
调优
调度优先级设置
nice能设置进程的最低优先级,格式:
nice -n 19 command
renice可以更改一个已经运行的进程的优先级。
进程绑定CPU
taskset -pc 7-10 10790
限定10790的进程只能运行在7-10之间的CPU上