系统CPU
概念
-
运行队列统计
包括正在运行的进程和在就绪队列等待的进程
如果就绪队列等待的进程越多,代表争抢CPU越严重
-
上下文切换
进程在CPU上切换会带来上下文切换
带来切换的原因:
- 进程的时间片用完(定时器中断)
- 调用阻塞的系统调用,导致进程主动放弃CPU使用权
- 随眠
-
中断
外部设备触发的通知事件
-
CPU使用率
- 用户态运行时间
- 内核态运行时间
- 等待IO的时间
- irq:高优先级代码处理硬件中断
- softirq:低优先级中断程序
vmstat
perf-vmstat列 | 描述 |
---|---|
r | 当前可运行的进程数 |
b | 等待IO完成的被阻塞的进程数 |
in | 中断的次数 |
cs | 上下文切换的次数 |
us | 用户态运行时间百分比 |
sy | 内核态运行时间百分比 包括irq softirq和system |
id | 系统空闲时间百分比 |
wa | 等待IO时间百分比 |
cs和us时间少,id时间多,代表系统处于空闲状态
us多代表系统调用占的时间更多
cs多代表进程大部分时间运行在用户态
r太多,代表CPU竞争激烈,资源出现不够用
wa多,代表设备IO性能出现问题
top
perf-top列 | 描述 |
---|---|
us | 用户态运行时间 |
sy | 内核态运行时间 |
ni | nice进程消耗的CPU时间 |
id | 空闲的时间 |
wa | 等待IO的时间 |
hi | irq的时间 |
si | softirq的时间 |
load average | 1/5/15分钟的平均负载 |
%CPU | 特定进程消耗的CPU时间 |
PRI | 进程优先级,值越大优先级越高 |
NI | nice值 |
TIME | 自启动以来已消耗的CPU时间(内核与用户态) |
系统内存
概念
-
高级缓存
CPU与内存之间有多级缓存来弥补它们之间的速度差
一个好的程序应该多的hit中缓存和尽量少的减少缓存不命中
通过工具,例如oprofile,可以分析出程序在哪个位置发生缓存不命中
-
内存页
一般机器会以4kb作为页的大小
但对于需要频繁申请内存的应用程序,如果页太小,就会发生很多次页缺失,和难以管理(太多页)
所以某些特定程序会通过使用大页2048kb,来提高性能
-
交换
当内存不够时,系统会通过把在内存的进程拷贝到硬盘
等这个进程再次运行时,再从硬盘交换会内存,继续运行
但这会导致性能非常低
-
缓冲缓存
读写磁盘时,使用缓存缓冲来加速数据的运输
-
活跃与非活跃内存
活跃内存代表被进程正在使用的内存
非活跃代表被进程申请了但还没使用的内存
Linux会找到非活跃的内存,在适当时机把它交换到硬盘
vmstat
perf-vmstatperf-vmstat-mem
列 | 描述 |
---|---|
swpd | 用于交换的内存总量 |
free | 未被使用的物理内存 |
buff | 缓冲 |
cache | 缓存 |
active | 活跃的内存 |
inactive | 非活跃内存 |
si | 从硬盘进来的交换速率 |
so | 到硬盘去的交换速率 |
pages paged in | 从硬盘读入缓冲的内存总量 |
pages paged out | 从缓存写入硬盘的内存总量 |
pages swapped in | 从交换去读入内存的内存总量 |
pages swapped out | 从系统内存写入交换的内存总量 |
use swap | 交换分区使用的容量 |
free swap | 可用的交换分区容量 |
total swap | 交换分区总量 |
top
perf-top列 | 描述 |
---|---|
%MEM | 进程使用内存量占系统内存的百分比 |
VIRT | 进程虚拟内存使用总量。包括分配但未使用的内存 |
SWAP | 进程使用交换区总量 |
RES | 进程实际使用物理内存总量 |
CODE | 进程可执行代码使用的物理内存总量 |
DATA | 进程数据和堆栈的内存总量 |
SHR | 进程共享内存总量 |
nDRT | 需要刷新到硬盘的脏页数量 |
Mem | 总量、使用量和空闲量 |
swap | 交换区的总量、使用量和空闲量 |
active | 活跃内存 |
inactive | 非活跃内存 |
buffers | 缓冲内存 |
free
perf-free列 | 描述 |
---|---|
Mem | 物理内存与交换区的总量 |
Used | 已使用的总量 |
free | 未使用的总量 |
shared | 忽略 |
buffers | 缓冲 |
cached | 缓存 |
-/+ buffers cache | 缓冲缓存 |
low | 低端内存 |
High | 高端内存 |
只有在Mem足够大的时候,缓冲和缓冲才会被Linux内核有效的利用起来,当发现IO性能下降的时候,有可能是系统内存不够导致的
进程CPU
概念
- 内核时间与用户时间
- 库时间与应用程序时间
- 应程序函数时间
time
perf-time列 | 描述 |
---|---|
User time | 用户态运行时间 |
System time | 内核态运行时间 |
Elapsed | 自启动以来经历的时间 |
Percent of CPU | 消耗CPU百分比 |
Major | 需要从磁盘读取内存页的缺页故障 |
Minor | 不需要访问磁盘的内存页缺页故障 |
Swaps | 进程被交换到磁盘的次数 |
Voluntary | 进程主动让出CPU的次数 |
Involuntary | 进程被动让出CPU的次数 |
Page size | 系统的页面大小 |
Exit status | 退出状态 |
strace
用于统计进程系统调用的运行时间
perf-strace列 | 描述 |
---|---|
% time | 系统函数占用系统调用总时间百分比 |
seconds | 此系统调用占用的总秒数 |
usecs/call | 一次系统调用花费的微妙数 |
calls | 系统函数总调用数 |
errors | 系统函数返回失败的次数 |
找出系统调用函数的花费时间,减少耗时长的系统调用,把阻塞系统调用改成非阻塞系统调用,或者使用更高效的系统调用
ltrace
库函数调用的时间统计
perf-ltrace列 | 描述 |
---|---|
% time | 此库函数所花的时间占总库函数调用时间的百分比 |
seconds | 此调用的总秒数 |
usecs/call | 一次调用花的微秒数 |
calls | 调用总数 |
function | 函数名 |
ps
perf-ps列 | 描述 |
---|---|
etime | 自启动以来花费的时间 |
time | 花费了多少CPU时间 |
pcpu | 占CPU百分比 |
command | 启动命令 |
ld
查看进程启动时间
perf-ld列 | 描述 |
---|---|
totoal startup time in dynamic loader | 应用程序开始执行开始,加载所花的时间 |
time needed for relocation | 符号重定向所花的时间(动态库) |
number of relocations | 已完成的重定位数量 |
number of relocations from cache | 预计算并使用的重定向数量 |
number of relative relocations | 相对重定位数量 |
time needed to load object | 加载应用程序使用的全部库所需时间 |
final number of relocations | 重定位总数 |
final number of relocations froms | 预计算重定位数量 |
上图可以看出重定位使用了83%的时间
这是加载动态库需要重定位带来的开销
如果使用prelink,可以把这个时间将为零
从而加快启动速度
gprof
用于分析应用程序函数的执行时间
gcc -pg -g3 -o app app.c
perf-gprof
oprofile
gprof需要加入编译选项
而oprofile不需要
也可以分析程序函数的调用时间
sudo opcontrol -d
perf-oprofile
进程内存
ps
perf-ps-mem列 | 描述 |
---|---|
-o | 需要跟踪的指标 |
vsz | 虚拟内存大小 |
rss | 实际使用的物理内存 |
tsiz | 程序代码的虚拟内存大小 |
dsiz | 程序数据结构与堆栈大小 |
majflt | 因读磁盘的缺页故障 |
minflt | 仅因申请内存的缺页故障 |
pmep | 内存百分比 |
command | 执行命令 |
valgrind
可以定位高速缓存缺失
perf-valgrind可以看到L1缓存有24.9%的读缺失和12.4%的写缺失
L2缓存有12.4%的写缺失
进一步的,可以通过cg_annotate来定位是哪个函数甚至哪行代码需要为缓存缺失负责
perf-cg_annotatecg_annotate --25571 --auto=yes
#定位哪一行有缓存缺失
磁盘IO
vmstat
perf-vmstat-io-default列 | 描述 |
---|---|
bo | 此间隔写入磁盘的总块数 |
bi | 读磁盘的总块数 |
wa | 等待IO所消耗的CPU时间 |
列 | 描述 |
---|---|
disks | 磁盘总数 |
partitions | 分区总数 |
total reads | 读请求数 |
merged reads | 为提升read,合并读操作,一般为相邻的磁盘块 |
read sectors | 读取的扇区总数 |
milli read | 读所花费的时间 |
writes | 写请求数 |
merged writes | 合并写 |
written sectors | 写入的总扇区数 |
milli writing | 写花费的时间 |
inprogress IO | 过程中的IO |
milli spent IO | 等待IO锁花费的毫秒数 |
可以看出读写IO,在性能上,应该关注合并写和合并读是否足够多。这要求应用程序,读写IO尽量利用局部性原理
如果等待IO过长,就有可能是应用程序使用过多的阻塞IO所导致的
iostat
用于统计IO读写速率
perf-iostat列 | 描述 |
---|---|
tps | 每秒的读写请求数 |
Blk_read/s | 每秒读的速率 |
Blk_writn/s | 每秒写速率 |
Blk_read | 时间间隔读总次数 |
Blk_write | 时间间隔写总次数 |
列 | 描述 |
---|---|
rrqm/s | 合并读的数量 |
wrqm/s | 合并写的数量 |
r/s | 每秒提交的读请求 |
w/s | 每秒提交的写请求 |
rsec/s | 每秒读取的扇区数 |
wsec/s | 每秒写入的扇区数 |
rkB/s | 每秒读取的数据 |
wkB/s | 每秒写入的数据 |
avgrq-sz | 请求扇区的平均大小 |
avgqu-sz | 请求队列的平均大小 |
await | 读写请求等待的时间和执行的平均时间 |
svctm | 读/写磁盘实际花费的平均时间 |
%until | 利用率 |
上图可以看出,磁盘的利用率达到100%
等待队列长度avgqu-sz相当高
等待时间await很长
执行时间svctm很低
这代表磁盘已经达到饱和状态
网友评论