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 任务当前使用的可用物理内存比例。