Linux内存、性能分析详解

在做双十一投放红包项目时,做压力测试,分析性能问题,用到了一些linux工具,以此做了一些总结:

TOP

启动 top 
top 的全屏对话模式可分为3部分:系统信息栏、命令输入栏、进程列表栏:
top - 20:05:40 up 14 days,  1:49,  2 users,  load average: 0.31, 0.33, 0.60
Tasks: 453 total,   1 running, 452 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.8%us,  0.1%sy,  0.0%ni, 99.1%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  65864020k total, 17787480k used, 48076540k free,   237748k buffers
Swap:  4194300k total,        0k used,  4194300k free,  4512088k cached

   PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                               
 21396 root      20   0 42.9g  11g  21m S 88.8 18.5 195:43.89 java                                                                 
   107 root      20   0     0    0    0 S  2.0  0.0   0:21.89 events/8                                                             
     1 root      20   0 19232 1512 1224 S  0.0  0.0   0:01.74 init                                                                 
     2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd                                                             
     3 root      RT   0     0    0    0 S  0.0  0.0   0:00.23 migration/0                                                           
     4 root      20   0     0    0    0 S  0.0  0.0   0:00.32 ksoftirqd/0 


第一部分 -- 最上部的 系统信息栏 : 
第一行(top): 
    “00:11:04”为系统当前时刻; 
    “3:35”为系统启动后到现在的运作时间; 
    “2 users”为当前登录到系统的用户,更确切的说是登录到用户的终端数 -- 同一个用户同一时间对系统多个终端的连接将被视为多个用户连接到系统,这里的用户数也将表现为终端的数目; 
    “load average”为当前系统负载的平均值,后面的三个值分别为1分钟前、5分钟前、15分钟前进程的平均数,一般的可以认为这个数值超过 CPU 数目时,CPU 将比较吃力的负载当前系统所包含的进程;
第二行(Tasks): 
    “59 total”为当前系统进程总数; 
    “1 running”为当前运行中的进程数; 
    “58 sleeping”为当前处于等待状态中的进程数; 
    “0 stoped”为被停止的系统进程数; 
    “0 zombie”为被复原的进程数; 
第三行(Cpus): 
分别表示了 CPU 当前的使用率; 
0.3% us 用户空间占用CPU百分比 
1.0% sy 内核空间占用CPU百分比
0.0% ni 用户进程空间内改变过优先级的进程占用CPU百分比
98.7% id 空闲CPU百分比
0.0% wa 等待输入输出的CPU时间百分比
0.0% hi 
0.0% si
第四行(Mem): 
Mem: 191272k total 物理内存总量
173656k used 使用的物理内存总量
17616k free 空闲内存总量
22052k buffers 用作内核缓存的内存量
Swap: 192772k total 交换区总量
第五行(Swap):
         表示类别同第四行(Mem),但此处反映着交换分区(Swap)的使用情况。通常,交换分区(Swap)被频繁使用的情况,将被视作物理内存不足而造成的
 0k used 使用的交换区总量
192772k free 空闲交换区总量
123988k cached 缓冲的交换区总量。内存中的内容被换出到交换区,而后又被换入到内存,但使用过的交换区尚未被覆盖, 该数值即为这些内容已存在于内存中的交换区的大小。相应的内存再次被换出时可不必再对交换区写入。 
第二部分 -- 中间部分的内部命令提示栏: 
  top 运行中可以通过 top 的内部命令对进程的显示方式进行控制。内部命令如下表: 
  s - 改变画面更新频率 
  l - 关闭或开启第一部分第一行 top 信息的表示 
  t - 关闭或开启第一部分第二行 Tasks 和第三行 Cpus 信息的表示 
  m - 关闭或开启第一部分第四行 Mem 和 第五行 Swap 信息的表示 
  N - 以 PID 的大小的顺序排列表示进程列表(第三部分后述) 
  P - 以 CPU 占用率大小的顺序排列进程列表 (第三部分后述) 
  M - 以内存占用率大小的顺序排列进程列表 (第三部分后述) 
  h - 显示帮助 
  n - 设置在进程列表所显示进程的数量 
  q - 退出 top 

第三部分 -- 最下部分的进程列表栏: 
序号  列名  含义  
a  PID  进程id  
b  PPID  父进程id  
c  RUSER  Real user name  
d  UID  进程所有者的用户id  
e  USER  进程所有者的用户名  
f  GROUP  进程所有者的组名  
g  TTY  启动进程的终端名。不是从终端启动的进程则显示为 ?  
h  PR  优先级  
i  NI  nice值。负值表示高优先级,正值表示低优先级  
j  P  最后使用的CPU,仅在多CPU环境 下有意义  
k  %CPU  上次更新到现在的CPU时间占用百分比  
l  TIME  进程使用的CPU时间总计,单位秒  
m  TIME+  进程使用的CPU时间总计,单位1/100秒  
n  %MEM  进程使用的物理内存 百分比  
o  VIRT  进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES  
p  SWAP  进程使用的虚拟内存中,被换出的大小,单位kb。  
q  RES  进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA  
r  CODE  可执行代码占用的物理 内存大小,单位kb  
s  DATA  可执行代码以外的部分(数据 段+栈)占用的物理 内存大小,单位kb  
t  SHR  共享内存大小,单位kb  
u  nFLT  页面错误次数  
v  nDRT  最后一次写入到现在,被修改过的页面数。  
w  S  进程状态。
            D =不可中断的睡眠状态
            R =运行
            S =睡眠
            T =跟踪/停止
            Z =僵尸进程  
x  COMMAND  命令名/命令行  
y  WCHAN  若该进程在睡眠,则显示睡眠中的系统函数名  
z  Flags  任务标志,参考 sched.h  

默认情况下仅显示比较重要的  PID、USER、PR、NI、VIRT、RES、SHR、S、%CPU、%MEM、TIME+、COMMAND  列。可以通过下面的快捷键来更改显示内容。
更改显示内容通过 f 键可以选择显示的内容。按 f 键之后会显示列的列表,按 a-z  即可显示或隐藏对应的列,最后按回车键确定。
按 o 键可以改变列的显示顺序。按小写的 a-z 可以将相应的列向右移动,而大写的 A-Z  可以将相应的列向左移动。最后按回车键确定。
按大写的 F 或 O 键,然后按 a-z 可以将进程按照相应的列进行排序。而大写的  R 键可以将当前的排序倒转。 

top命令使用过程中,还可以使用一些交互的命令来完成其它参数的功能。这些命令是通过快捷键启动的。
<空格>:立刻刷新。
P:根据CPU使用大小进行排序。
T:根据时间、累计时间排序。
q:退出top命令。
m:切换显示内存信息。
t:切换显示进程和CPU状态信息。
c:切换显示命令名称和完整命令行。
M:根据使用内存大小进行排序。
W:将当前设置写入~/.toprc文件中。这是写top配置文件的推荐方法。
 
可以看到,top命令是一个功能十分强大的监控系统的工具,对于系统管理员而言尤其重要。但是,它的缺点是会消耗很多系统资源。

free命令

20:09 [[email protected]]$ free
             total       used       free     shared    buffers     cached
Mem:      65864020   17786912   48077108        184     237748    4512092
-/+ buffers/cache:   13037072   52826948
Swap:      4194300          0    4194300
下面是对这些数值的解释:
total:总计物理内存的大小。
used:已使用多大。
free:可用有多少。
Shared:多个进程共享的内存总额。
Buffers/cached:磁盘缓存的大小。
第三行(-/+ buffers/cached):
used:已使用多大。
free:可用有多少。
第四行就不多解释了。

区别:第二行(mem)的used/free与第三行(-/+ buffers/cache) used/free的区别。 这两个的区别在于使用的角度来看,第一行是从OS的角度来看,因为对于OS,buffers/cached 都是属于被使用,所以他的可用内存是48077108 KB,已用内存是17786912 KB,其中包括,内核(OS)使用+Application(X, oracle,etc)使用的+buffers+cached.
第三行所指的是从应用程序角度来看,对于应用程序来说,buffers/cached 是等于可用的,因为buffer/cached是为了提高文件读取的性能,当应用程序需在用到内存的时候,buffer/cached会很快地被回收。
 
free命令是用来查看内存使用情况的主要命令。和top命令相比,它的优点是使用简单,并且只占用很少的系统资源。通过-S参数可以使用free命令不间断地监视有多少内存在使用,这样可以把它当作一个方便实时监控器。
#free -b -s5
使用这个命令后终端会连续不断地报告内存使用情况(以字节为单位),每5秒更新一次。

我们通过free命令查看机器空闲内存时,会发现free的值很小。这主要是因为,在linux中有这么一种思想,内存不用白不用,因此它尽可能的cache和buffer一些数据,以方便下次使用。但实际上这些内存也是可以立刻拿来使用的。
所以从应用程序的角度来说,可用内存=系统free memory+buffers+cached。

vmstat

vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况。这个命令是我查看Linux/Unix最喜爱的命令,一个是Linux/Unix都支持,二是相比top,我可以看到整个机器的CPU,内存,IO的使用情况,而不是单单看到各个进程的CPU使用率和内存使用率(使用场景不一样)。
一般vmstat工具的使用是通过两个数字参数来完成的,第一个参数是采样的时间间隔数,单位是秒,第二个参数是采样的次数,如:
2表示每个两秒采集一次服务器状态,1表示只采集一次:
20:10 [[email protected]]$ vmstat 2 1
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 48077340 237748 4512096    0    0     0     0    1    1  1  0 99  0  0

每个2s报告一次内存情况:
2表示每个两秒采集一次服务器状态,1表示只采集一次:
20:11 [[email protected]]$ vmstat 2
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 48077384 237748 4512096    0    0     0     0    1    1  1  0 99  0  0
 0  0      0 48077088 237748 4512096    0    0     0    14  879  667  0  0 100  0  0
 0  0      0 48077072 237748 4512096    0    0     0     0  966  679  0  0 100  0  0
 0  0      0 48077072 237748 4512096    0    0     0     6  874  627  0  0 100  0  0
r 表示运行队列(就是说多少个进程真的分配到CPU),我测试的服务器目前CPU比较空闲,没什么程序在跑,当这个值超过了CPU数目,就会出现CPU瓶颈了。这个也和top的负载有关系,一般负载超过了3就比较高,超过了5就高,超过了10就不正常了,服务器的状态很危险。top的负载类似每秒的运行队列。如果运行队列过大,表示你的CPU很繁忙,一般会造成CPU使用率很高。
b 表示阻塞的进程,这个不多说,进程阻塞,大家懂的。
swpd 虚拟内存已使用的大小,如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。
free   空闲的物理内存的大小,我的机器内存总共8G,剩余3415M。
buff   Linux/Unix系统是用来存储,目录里面有什么内容,权限等的缓存,我本机大概占用300多M
cache cache直接用来记忆我们打开的文件,给文件做缓冲,我本机大概占用300多M(这里是Linux/Unix的聪明之处,把空闲的物理内存的一部分拿来做文件和目录的缓存,是为了提高 程序执行的性能,当程序使用内存时,buffer/cached会很快地被使用。)
si  每秒从磁盘读入虚拟内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉。我的机器内存充裕,一切正常。
so  每秒虚拟内存写入磁盘的大小,如果这个值大于0,同上。
bi  块设备每秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte,我本机上没什么IO操作,所以一直是0,但是我曾在处理拷贝大量数据(2-3T)的机器上看过可以达到140000/s,磁盘写入速度差不多140M每秒
bo 块设备每秒发送的块数量,例如我们读取文件,bo就要大于0。bi和bo一般都要接近0,不然就是IO过于频繁,需要调整。
in 每秒CPU的中断次数,包括时间中断
cs 每秒上下文切换次数,例如我们调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目,例如在apache和nginx这种web服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调,压测,直到cs到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换,导致CPU干正经事的时间少了,CPU没有充分利用,是不可取的。
us 用户CPU时间,我曾经在一个做加密解密很频繁的服务器上,可以看到us接近100,r运行队列达到80(机器在做压力测试,性能表现不佳)。
sy 系统CPU时间,如果太高,表示系统调用时间长,例如是IO操作频繁。
id  空闲 CPU时间,一般来说,id + us + sy = 100,一般我认为id是空闲CPU使用率,us是用户CPU使用率,sy是系统CPU使用率。
wt 等待IO CPU时间。

iostat

iostat主要用于监控系统设备的IO负载情况,iostat首次运行时显示自系统启动开始的各项统计信息,之后运行iostat将显示自上次运行该命令以后的统计信息。用户可以通过指定统计的次数和时间来获得所需的统计信息。
iostat -d -k 2
参数 -d 表示,显示设备(磁盘)使用状态;
-k某些使用block为单位的列强制使用Kilobytes为单位;2表示,数据显示每隔2秒刷新一次:
20:12 [[email protected]]$ iostat -d -k 2
Linux 2.6.32-573.el6.x86_64 (a02.atm.ad.youku)        11/16/16        _x86_64_        (24 CPU)

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               0.55         0.24         7.94     288367    9661881

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               0.00         0.00         0.00          0          0

输出信息的意义:
tps:该设备每秒的传输次数(Indicate the number of transfers per second that were issued to the device.)。"一次传输"意思是"一次I/O请求"。多个逻辑请求可能会被合并为"一次I/O请求"。"一次传输"请求的大小是未知的。
kB_read/s:每秒从设备(drive expressed)读取的数据量;
kB_wrtn/s:每秒向设备(drive expressed)写入的数据量;
kB_read:读取的总数据量;
kB_wrtn:写入的总数量数据量;这些单位都为Kilobytes。
上面的例子中,我们可以看到磁盘sda以及它的各个分区的统计数据,当时统计的磁盘总TPS是 0.55 ,下面是各个分区的TPS。(因为是瞬间值,所以总TPS并不严格等于各个分区TPS的总和)

指定监控的设备名称为sda,该命令的输出结果和上面命令完全相同。
 iostat -d sda 2
默认监控所有的硬盘设备,现在指定只监控sda。

-x 参数
iostat还有一个比较常用的选项-x,该选项将用于显示和io相关的扩展数据。

iostat -d -x -k 1 10
Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
sda          1.56  28.31  7.80 31.49   42.51    2.92    21.26     1.46     1.16     0.03    0.79   2.62  10.28
Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
sda          2.00  20.00 381.00  7.00 12320.00  216.00  6160.00   108.00    32.31     1.75    4.50   2.17  84.20

输出信息的含义
rrqm/s:每秒这个设备相关的读取请求有多少被Merge了(当系统调用需要读取数据的时候,VFS将请求发到各个FS,如果FS发现不同的读取请求读取的是相同Block的数据,FS会将这个请求合并Merge);wrqm/s:每秒这个设备相关的写入请求有多少被Merge了。
rsec/s:每秒读取的扇区数;
wsec/:每秒写入的扇区数。
rKB/s:The number of read requests that were issued to the device per second;
wKB/s:The number of write requests that were issued to the device per second;
avgrq-sz 平均请求扇区的大小
avgqu-sz 是平均请求队列的长度。毫无疑问,队列长度越短越好。   
await:  每一个IO请求的处理的平均时间(单位是微秒毫秒)。这里可以理解为IO的响应时间,一般地系统IO响应时间应该低于5ms,如果大于10ms就比较大了。
         这个时间包括了队列时间和服务时间,也就是说,一般情况下,await大于svctm,它们的差值越小,则说明队列时间越短,反之差值越大,队列时间越长,说明系统出了问题。
svctm    表示平均每次设备I/O操作的服务时间(以毫秒为单位)。如果svctm的值与await很接近,表示几乎没有I/O等待,磁盘性能很好,如果await的值远高于svctm的值,则表示I/O队列等待太长,         系统上运行的应用程序将变慢。
%util: 在统计时间内所有处理IO时间,除以总共统计时间。例如,如果统计间隔1秒,该设备有0.8秒在处理IO,而0.2秒闲置,那么该设备的%util = 0.8/1 = 80%,所以该参数暗示了设备的繁忙程度
。一般地,如果该参数是100%表示设备已经接近满负荷运行了(当然如果是多磁盘,即使%util是100%,因为磁盘的并发能力,所以磁盘使用未必就到了瓶颈)。

-c 参数:iostat还可以用来获取cpu部分状态值:
20:15 [[email protected]]$ iostat -c 1 10
Linux 2.6.32-573.el6.x86_64 (a02.atm.ad.youku)        11/16/16        _x86_64_        (24 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.77    0.00    0.12    0.01    0.00   99.10

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.17    0.00    0.00    0.00    0.00   99.83

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.17    0.00    0.04    0.00    0.00   99.79

常见用法
iostat -d -k 1 10         #查看TPS和吞吐量信息(磁盘读写速度单位为KB)
iostat -d -m 2            #查看TPS和吞吐量信息(磁盘读写速度单位为MB)
iostat -d -x -k 1 10      #查看设备使用率(%util)、响应时间(await) iostat -c 1 10 #查看cpu状态
例如:
ostat -d -k 1 |grep sda10
Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda10            60.72        18.95        71.53  395637647 1493241908
sda10           299.02      4266.67       129.41       4352        132
sda10           483.84      4589.90      4117.17       4544       4076
sda10           218.00      3360.00       100.00       3360        100
sda10           546.00      8784.00       124.00       8784        124
sda10           827.00     13232.00       136.00      13232        136
上面看到,磁盘每秒传输次数平均约400;每秒磁盘读取约5MB,写入约1MB。
iostat -d -x -k 1
Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
sda          1.56  28.31  7.84 31.50   43.65    3.16    21.82     1.58     1.19     0.03    0.80   2.61  10.29
sda          1.98  24.75 419.80  6.93 13465.35  253.47  6732.67   126.73    32.15     2.00    4.70   2.00  85.25
sda          3.06  41.84 444.90 54.08 14204.08 2048.98  7102.04  1024.49    32.57     2.10    4.21   1.85  92.24
可以看到磁盘的平均响应时间<5ms,磁盘使用率>80。磁盘响应正常,但是已经很繁忙了。

备注

测量一个进程占用了多少内存,linux为我们提供了一个很方便的方法,/proc目录为我们提供了所有的信息,实际上top等工具也通过这里来获取相应的信息。
/proc/meminfo 机器的内存使用信息
/proc/pid/maps pid为进程号,显示当前进程所占用的虚拟地址。
/proc/pid/statm 进程所占用的内存

参考:http://www.cnblogs.com/xd502djj/archive/2011/03/01/1968041.html
http://www.cnblogs.com/ggjucheng/archive/2012/01/05/2312625.html
http://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858810.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章