Linux CPU性能分析与监控——vmstat、top
Linux性能监控工具汇总:
- iostat 磁盘性能监控
- vmstat 虚拟内存性能监控、CPU监控(进程上下文切换、CPU利用率)
- top 系统负载、CPU使用率、各个进程的详细报告(CPU使用率、内存使用情况)等
- free 内存使用情况。
- ps ps命令不算是性能监控工具,但是可以使用ps配合上述命令,找到占有系统资源较高的进程
本文重点讲下vmstat的用法,其他如top不做讲解,基本上vmstat的报告能看到,top的也差不多。top报告如有不懂得地方,可以man top
一、vmstat用法
vmstat命令主要用于查看虚拟内存的,但是也可以查看系统其他资源的使用情况,如CPU
vmstat [interval] [count]
vmstat选项
-a 显示活跃内存(active)和非活跃内存(inact)
-f 显示从系统启动至今的fork数量
-m 显示slabinfo
-s 静态显示内存相关信息
首先运行一个默认命令, 根据输出结果,解释下各个字段的含义,有助于下面的分析。
[root@master ~]# vmstat
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 431340 44840 211744 0 0 5 2 149 9 2 4 95 0 0
[root@minion ~]# vmstat -a
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free inact active si so bi bo in cs us sy id wa st
1 0 0 757496 64916 83772 0 0 85 7 56 42 1 3 96 0 0
各个字段对应的项含义如下
procs
- r 正在等待运行的进程数
- b 在uninterruptible 睡眠中的进程数
memory
- swpd 以使用的swap空间
- free 剩余的物理内存
- buff buffer
- cache cache
- inact 非活动的内数量(-a选项)
- active 活动的内存的数量(-a选项)
swap
- si 从磁盘交换的内存大小
- so 交换到磁盘的内存大小
io
- bi 从块设备接收的块(block/s)
- bo 发送给块设备的块(block/s).如果这个值长期不为0,说明内存可能有问题,因为没有使用到缓存(当然,不排除直接I/O的情况,但是一般很少有直接I/O的)
system
- in 每秒的中断次数,包括时钟中断
- cs 进程上下文切换次数
cpu
- us 用户进程占用CPU时间比例
- sy 系统占用CPU时间比例
- id CPU空闲时间比
- wa IO等待时间比(IO等待高时,可能是磁盘性能有问题了)
- st steal time
二、CPU篇
2.1 监控指标
CPU利用率。根据经验来看,用户空间进程占用CPU比例在 65-70%之间,内核(系统)CPU比例在30%-35%之间,空闲比例在0%-5%之间。一般不能超过这个比例,超过这个比例,系统性能就会降低,平均负载升高,这点将会在下面的测试中看到。
进程上下文切换。上下文切换和CPU利用率应该联系起来,如果CPU利用率低,那么上下文切换稍高点也能接受。上下文切换也是需要消耗CPU资源的,频繁的切换必将使得CPU利用率升高。
运行队列中等待运行的进程数。每个CPU核心中等待处理的进程数不应该超过3个线程/进程。如4核心的机器,那么队列的最大值应该不超过12个。
平均负载。平均负载值是平均每核心CPU的负载应该控制在0.7。最好不要超过1.
一般,我是使用top命令和vmstat命令一起看,top命令可以看到整体情况,也可以看到每个任务消耗资源的情况。使用vmstat命令查看队列中的任务书、进程上下文切换。
下面是一个CPU密集型程序,采用多线程(20个线程)去循环将一个全局变量+1.
这个程序如下
#!/usr/bin/python
import threading
count = 0
class Test(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global count
for i in xrange(1,100000000): #100000000
count += 1
print count
if __name__ == '__main__':
threads = []
for i in range(10):
thread = Test()
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
print count
2.2 程序运行前
我在程序运行前使用top命令和vmstat命令查看相关报告
vmstat报告
[root@master ~]# vmstat 2 10
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 432696 43672 211724 0 0 6 2 148 715 2 4 94 0 0
0 0 0 432688 43672 211724 0 0 0 0 20 17 0 0 100 0 0
0 0 0 432688 43672 211724 0 0 0 0 16 17 0 0 100 0 0
0 0 0 432432 43672 211724 0 0 0 0 54 43 0 1 99 0 0
0 0 0 432400 43672 211724 0 0 0 0 38 37 0 0 100 0 0
0 0 0 432376 43672 211724 0 0 0 0 88 65 0 1 99 0 0
0 0 0 432120 43672 211724 0 0 0 0 49 35 0 1 99 0 0
0 0 0 432152 43672 211724 0 0 0 0 31 28 0 0 99 0 0
0 0 0 432152 43672 211724 0 0 0 0 29 26 0 0 100 0 0
0 0 0 432152 43672 211724 0 0 0 0 15 16 0 0 100 0 0
top报告
[root@master ~]# top
top - 12:11:37 up 7:07, 3 users, load average: 0.00, 0.00, 0.02
Tasks: 114 total, 1 running, 113 sleeping, 0 stopped, 0 zombie
Cpu0 : 1.8%us, 3.3%sy, 0.0%ni, 94.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu1 : 1.3%us, 3.8%sy, 0.0%ni, 94.8%id, 0.0%wa, 0.0%hi, 0.1%si, 0.0%st
Mem: 1004412k total, 573856k used, 430556k free, 45160k buffers
Swap: 2047992k total, 0k used, 2047992k free, 211748k cached
根据top报告和vmstat报告,我们完全可以得出结论——系统性能良好。因为各个指标的值都不高
2.3 程序运行时
vmstat报告
[root@master ~]# vmstat 2 10
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
21 0 0 423072 43640 211724 0 0 6 2 142 506 2 4 95 0 0
20 0 0 423064 43640 211724 0 0 0 0 2085 78125 26 73 1 0 0
20 0 0 423064 43640 211724 0 0 0 0 2038 79752 24 74 1 0 0
20 0 0 423064 43640 211724 0 0 0 0 2057 78022 25 74 1 0 0
20 0 0 423064 43640 211724 0 0 0 0 2045 85145 25 73 2 0 0
20 0 0 423032 43640 211724 0 0 0 12 2002 68602 25 73 2 0 0
20 0 0 422908 43640 211724 0 0 0 0 2065 79101 25 73 1 0 0
20 0 0 422908 43640 211724 0 0 0 0 2048 78424 26 73 1 0 0
10 0 0 422940 43640 211724 0 0 0 0 2039 69779 22 76 2 0 0
21 0 0 422940 43640 211724 0 0 0 0 2050 81712 26 73 2 0 0
top报告
[root@master ~]# top
top - 10:55:10 up 5:51, 3 users, load average: 15.01, 11.58, 6.21
Tasks: 115 total, 1 running, 114 sleeping, 0 stopped, 0 zombie
Cpu0 : 27.8%us, 72.2%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu1 : 22.2%us, 77.8%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1004412k total, 581836k used, 422576k free, 43656k buffers
Swap: 2047992k total, 0k used, 2047992k free, 211724k cached
运行时的情况看起来就十分不好了。我重点关注了这几个值:
top报告分析
- load average: 15.01, 11.58, 6.21
- %sys: 都已经达到了70%以上
- id% 都是 0
vmstat报告分析
- r 运行队列中等待的线程/进程基本上都是20左右
- cs 上下文切换每秒80000次左右
从上述分析中可以看出,系统系能已经很差了。这里我尝试做一个分析,为什么系统占用CPU的利用率这么高?我认为是程序运行时的进程上下文频繁切换所导致的,这是因为进程/线程的调度室通过内核子系统进程调度程序来调度的,频繁的切换说明进程调度程序也是十分频繁的的占用CPU,因此导致系统占用CPU的时间很高;此外,系统调用也是耗费了一部分时间的。因此系统占用CPU的比例很高,而用户空间进程占有CPU的比例相对就低了很多。系统就是给用户提供服务的,如果大部分资源都被系统给占用,那这个用户还能做什么工作呢?
补充top 字段含义:
%hi , IRQ。如果这个值不均衡,则说明没有设置中断均衡。设置方法可参考我之前的文章多队列网卡中断均衡
- %si soft IRQ,即软中断
- PR 优先级
- NI nice值
- VIRT virtual image(kb)
- RES Resident size。已使用的非swap物理内存
- SHR 共享内存大小(kb)
- %CPU 占总CPU时间的百分比。这个值是和上次更新至现在的CPU使用率。如top命令3秒更新一次数据,那这个值就是这个3秒内的CPU使用率
- %MEM 任务当前使用的可用物理内存比例。