系统CPU
概念
-
运行队列统计
包括正在运行的进程和在就绪队列等待的进程
如果就绪队列等待的进程越多,代表争抢CPU越严重
-
上下文切换
进程在CPU上切换会带来上下文切换
带来切换的原因:
- 进程的时间片用完(定时器中断)
- 调用阻塞的系统调用,导致进程主动放弃CPU使用权
- 随眠
-
中断
外部设备触发的通知事件
-
CPU使用率
- 用户态运行时间
- 内核态运行时间
- 等待IO的时间
- irq:高优先级代码处理硬件中断
- softirq:低优先级中断程序
vmstat
| 列 | 描述 |
|---|---|
| r | 当前可运行的进程数 |
| b | 等待IO完成的被阻塞的进程数 |
| in | 中断的次数 |
| cs | 上下文切换的次数 |
| us | 用户态运行时间百分比 |
| sy | 内核态运行时间百分比 包括irq softirq和system |
| id | 系统空闲时间百分比 |
| wa | 等待IO时间百分比 |
cs和us时间少,id时间多,代表系统处于空闲状态
us多代表系统调用占的时间更多
cs多代表进程大部分时间运行在用户态
r太多,代表CPU竞争激烈,资源出现不够用
wa多,代表设备IO性能出现问题
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
| 列 | 描述 |
|---|---|
| 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
| 列 | 描述 |
|---|---|
| %MEM | 进程使用内存量占系统内存的百分比 |
| VIRT | 进程虚拟内存使用总量。包括分配但未使用的内存 |
| SWAP | 进程使用交换区总量 |
| RES | 进程实际使用物理内存总量 |
| CODE | 进程可执行代码使用的物理内存总量 |
| DATA | 进程数据和堆栈的内存总量 |
| SHR | 进程共享内存总量 |
| nDRT | 需要刷新到硬盘的脏页数量 |
| Mem | 总量、使用量和空闲量 |
| swap | 交换区的总量、使用量和空闲量 |
| active | 活跃内存 |
| inactive | 非活跃内存 |
| buffers | 缓冲内存 |
free
| 列 | 描述 |
|---|---|
| Mem | 物理内存与交换区的总量 |
| Used | 已使用的总量 |
| free | 未使用的总量 |
| shared | 忽略 |
| buffers | 缓冲 |
| cached | 缓存 |
| -/+ buffers cache | 缓冲缓存 |
| low | 低端内存 |
| High | 高端内存 |
只有在Mem足够大的时候,缓冲和缓冲才会被Linux内核有效的利用起来,当发现IO性能下降的时候,有可能是系统内存不够导致的
进程CPU
概念
- 内核时间与用户时间
- 库时间与应用程序时间
- 应程序函数时间
time
| 列 | 描述 |
|---|---|
| User time | 用户态运行时间 |
| System time | 内核态运行时间 |
| Elapsed | 自启动以来经历的时间 |
| Percent of CPU | 消耗CPU百分比 |
| Major | 需要从磁盘读取内存页的缺页故障 |
| Minor | 不需要访问磁盘的内存页缺页故障 |
| Swaps | 进程被交换到磁盘的次数 |
| Voluntary | 进程主动让出CPU的次数 |
| Involuntary | 进程被动让出CPU的次数 |
| Page size | 系统的页面大小 |
| Exit status | 退出状态 |
strace
用于统计进程系统调用的运行时间
| 列 | 描述 |
|---|---|
| % time | 系统函数占用系统调用总时间百分比 |
| seconds | 此系统调用占用的总秒数 |
| usecs/call | 一次系统调用花费的微妙数 |
| calls | 系统函数总调用数 |
| errors | 系统函数返回失败的次数 |
找出系统调用函数的花费时间,减少耗时长的系统调用,把阻塞系统调用改成非阻塞系统调用,或者使用更高效的系统调用
ltrace
库函数调用的时间统计
| 列 | 描述 |
|---|---|
| % time | 此库函数所花的时间占总库函数调用时间的百分比 |
| seconds | 此调用的总秒数 |
| usecs/call | 一次调用花的微秒数 |
| calls | 调用总数 |
| function | 函数名 |
ps
| 列 | 描述 |
|---|---|
| etime | 自启动以来花费的时间 |
| time | 花费了多少CPU时间 |
| pcpu | 占CPU百分比 |
| command | 启动命令 |
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
oprofile
gprof需要加入编译选项
而oprofile不需要
也可以分析程序函数的调用时间
sudo opcontrol -d
进程内存
ps
| 列 | 描述 |
|---|---|
| -o | 需要跟踪的指标 |
| vsz | 虚拟内存大小 |
| rss | 实际使用的物理内存 |
| tsiz | 程序代码的虚拟内存大小 |
| dsiz | 程序数据结构与堆栈大小 |
| majflt | 因读磁盘的缺页故障 |
| minflt | 仅因申请内存的缺页故障 |
| pmep | 内存百分比 |
| command | 执行命令 |
valgrind
可以定位高速缓存缺失
可以看到L1缓存有24.9%的读缺失和12.4%的写缺失
L2缓存有12.4%的写缺失
进一步的,可以通过cg_annotate来定位是哪个函数甚至哪行代码需要为缓存缺失负责
cg_annotate --25571 --auto=yes
#定位哪一行有缓存缺失
磁盘IO
vmstat
| 列 | 描述 |
|---|---|
| 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读写速率
| 列 | 描述 |
|---|---|
| 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很低
这代表磁盘已经达到饱和状态







网友评论